耗時18個月,我們構建了一個真正可擴展的無服務器 SQL 數據庫

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在經歷了 18 個月的挑戰之後,我們推出了第一個真正可擴展的無服務器 SQL 數據庫。這東西"},{"type":"link","attrs":{"href":"https:\/\/cockroachlabs.cloud\/signup","title":null,"type":null},"content":[{"type":"text","text":"現在可以免費使用"}]},{"type":"text","text":"!請繼續閱讀本文,瞭解 CockroachDB 無服務器是如何由內而外工作的,以及我們爲什麼可以免費提供這種服務——不是在某段時間內免費,而是永遠免費。要實現這一目標,需要進行許多重大的、迷人的工程。你一定會喜歡這個故事的。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是 CockroachDB 無服務器"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你之前創建了一個數據庫,根據你的預期流量,你可能需要評估使用的服務器數量。加入預測值過低,你的數據庫就在負載中倒下,從而導致停機。如果預測值過高,或者流量猛增,你就會浪費錢在這些空閒的服務器上。能否有更好的辦法呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"無服務器意味着你無需考慮服務器的問題。誠然,有些服務器正忙於處理應用程序的請求,但這是我們的問題,與你無關。通過這些努力,我們可以在幕後分配、配置和維護服務器。你不需要爲服務器付費,而是爲你的應用程序在數據庫上的請求和數據所消耗的存儲付費。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你只需要爲實際使用的花費買單,而不必預先計算可能的花費。如果你用得多,我們將會自動分配更多的硬件以處理增加的負載。如果你用得少,那麼你就可以少付點錢,甚至不用付錢。如果你能設定一個有保障的每月消費限額,那麼你將永遠不會對賬單感到驚訝。如果你接近該限額,我們將提醒你,在你超出該限額時,甚至免費提供性能基線水平。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這使我想到最重要的部分。CockroachDB 無服務器是“永遠免費”的,每月爲請求和存儲提供慷慨(且永不終止)的信用。只要點擊幾次鼠標或者調用一個 API,你就能在幾秒鐘內創建一個全功能的 CockroachDB 數據庫。你將得到一個“永遠在線”的數據庫,它可以在數據中心故障時依然存在,併爲你的數據保留多個加密副本,這樣你就不會因爲黑客或硬件故障而丟失數據。它能夠自動且透明地擴展,以滿足你的需求,無論大小,都無需修改你的應用程序。它支持在線架構遷移,兼容 Postgres,並允許你獲得"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/docs\/stable\/enterprise-licensing.html","title":null,"type":null},"content":[{"type":"text","text":"企業特性"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在你選擇的任何應用環境中使用你喜歡的語言、SDK 或工具;使用 CockroachDB 無服務器並不意味着你必須使用無服務器計算服務,比如 AWS Lambda 或 Google Cloud Functions 等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們怎麼能承擔得起贈送這個東西呢?毫無疑問,我們希望你們中的一些人能夠成功地開發出應用程序,“大幹一場”,成爲付費用戶。但是,除了這些之外,我們還創建了一種創新的無服務器架構,允許我們在一個單一的底層物理 CockroachDB 數據庫集羣上安全地託管成千上萬的虛擬化 CockroachDB 數據庫集羣。這就是說,一個只有幾千字節存儲空間和少量請求的小型數據庫,其運行成本幾乎爲零,因爲它只是在一小塊物理硬件上運行。下面我會詳細地解釋一下它是如何工作的,但是這裏有一張圖讓你思考:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/69\/69146f9c7d971cb28f36e588f8d7d3de.jpeg","alt":"image.png","title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"單租戶架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在此之前,單個物理 CockroachDB 集羣是供單個用戶或組織專門使用的。這就是所謂的單租戶。在一些 CockroachDB 之前的版本中,我們已經添加了多租戶支持,這使得一個物理 CockroachDB 集羣可以由多個用戶或組織(稱爲“租戶”)共享。每一個租戶都有自己的虛擬化 CockroachDB 集羣,該集羣託管在物理 CockroachDB 集羣上,但是可以安全地隔離其他租戶集羣。你也許對虛擬機的工作方式很熟悉吧?它有點類似,僅用於數據庫集羣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要想有意義地解釋多租戶的工作方式,我需要回顧一下"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/docs\/stable\/architecture\/overview.html","title":null,"type":null},"content":[{"type":"text","text":"單租戶架構"}]},{"type":"text","text":"。首先,一個單租戶的 CockroachDB 集羣由任意數量的節點組成。每一個節點都用於數據存儲和計算,它們通常託管在自己的機器上。CockroachDB 在單個節點上具有分層架構。最高層是 SQL 層,用於解析、優化和執行 SQL 語句。這是通過"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/blog\/distributed-sql-key-value-store\/","title":null,"type":null},"content":[{"type":"text","text":"將高級 SQL 語句巧妙地轉換爲簡單的讀寫請求"}]},{"type":"text","text":",然後發送給底層的鍵值層。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"鍵值層維護一個事務性的、分佈式的、複製的鍵值存儲。這很拗口,所以讓我把它分解一下。每一個鍵都是一個唯一的字符串,映射爲任意值,就像在字典裏一樣。鍵值將這些鍵值對以排序的方式存儲,以便快速查找。鍵值對也被分組爲範圍。每個範圍包含全部鍵值對中連續的、不重疊的部分,按鍵排序。範圍分佈在可用的節點上,爲了高可用性,至少要複製三次。在全有或全無事務中,可以添加、刪除和更新鍵值對。下面有一個簡化的示例,展示瞭如何將更高級的 SQL 語句轉換爲簡單的 KV GET 調用:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/62\/62e95872586d8fca5369d7307a8a6c84.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在單租戶 CockroachDB 中,每個節點上的 SQL 層與鍵值層都在在同一個進程中。雖然 SQL 層總是調用在同一個節點上運行的鍵值實例,但是鍵值通常會“扇出”其他節點上運行的其他鍵值實例額外調用。這是因爲 SQL 所需要的數據往往位於分散在集羣中各節點的範圍內。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"多租戶架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎樣擴展這種單租戶架構以支持多個租戶?每個租戶都會覺得自己擁有自己專用的 CockroachDB 集羣,並在性能和安全方面與其他租戶隔離。但是如果我們試圖在租戶之間共享 SQL 層,這就很難實現了。某個租戶失控的 SQL 查詢可以輕易地影響同一進程中其他租戶的性能。另外,共享同一個進程會帶來很多難以可靠緩解的跨租戶安全威脅。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一種可能的解決方法是爲每一個租戶提供一套自己的隔離進程,同時運行 SQL 和鍵值層。但是,這造成另一個問題:我們不能在租戶之間共享鍵值存儲。這樣就消除了對哦住戶架構的一個主要優點:有效地將許多小型租戶的數據打包到共享的存儲層中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"考慮過這個問題後,我們認識到,通過分離一些組件並共享其他組件,可以很好的解決這個難題。由於 SQL 層難以共享,因此我們決定在每個租戶的進程中將它的鍵值層的事務組件和分發組件隔離開來。與此同時,在所有租戶共享的存儲節點上繼續運行鍵值的複製組件和存儲組件。這樣,我們可以得到“兩全其美”的效果:對於每個租戶來說,SQL 進程的安全性和隔離性,以及共享存儲節點的效率。下面是最新的圖表,展示了兩個隔離的每租戶 SQL 節點與共享存儲層之間的交互情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ef\/efa7ad8c632f40bbb665b6a3b00349c2.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"存儲節點不再運行租戶的 SQL 查詢,但它們仍然利用複雜的基礎設施,爲單租戶 CockroachDB 提供支持。節點故障的檢測和修復不會影響到數據的可用性。"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/docs\/stable\/architecture\/replication-layer.html#leases","title":null,"type":null},"content":[{"type":"text","text":"租賃者"}]},{"type":"text","text":",爲每個範圍提供讀取服務,協調寫入,根據活動情況進行移動。繁忙範圍會被自動分割;安靜範圍會被合併。基於負載的不同,範圍在各節點之間重新平衡。存儲層將熱範圍緩存在內存中,並將冷範圍推送到磁盤。跨可用性區域的三向複製確保你的數據存儲得到安全性和高可用性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在看到這種架構後,你可能會想知道共享存儲節點的安全性問題。爲了保護租戶數據,我們花費了大量時間設計和實施強有力的安全措施。每一個租戶都會鍵值密鑰空間的一個隔離的、受保護的部分。實現方法是"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/blog\/distributed-sql-key-value-store\/","title":null,"type":null},"content":[{"type":"text","text":"在 SQL 層生成的每個密鑰"}]},{"type":"text","text":"之前加上租戶的唯一標識符。而不是生成一個像 "},{"type":"codeinline","content":[{"type":"text","text":"\/\/\/"}]},{"type":"text","text":" 的鍵,SQL 將生成一個像 "},{"type":"codeinline","content":[{"type":"text","text":"\/\/\/\/"}]},{"type":"text","text":" 的鍵。這意味着由不同租戶生成的鍵值對在各自的範圍內進行隔離。另外,存儲節點還將認證所有來自 SQL 節點的通信,並每個租戶只能訪問以他們自己的租戶標識符爲前綴的密鑰。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了安全性外,我們還關心如何確保跨租戶的基本服務質量。如果多個租戶對同一個存儲節點執行鍵值調用,會發生什麼情況?爲了確保單個租戶無法壟斷存儲節點上的資源,我們測量來自每個租戶的讀取和寫入請求的數量和大小,如果超出某個閾值,則限制其活動。不像 SQL 語句,鍵值調用是相對簡單的操作,比如對鍵值對的 GET、PUT 和 DELETE,可以在一個共享進程中有效地調節。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"無服務器架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"等等……上一節不是說無服務器架構嗎?嗯,是的,也不是。如上所述,我們對核心數據庫架構進行了重大升級,以支持多租戶。但這只是故事的一半。要讓無服務器成爲可能,我們還需要對如何部署和操作多租戶 CockroachDB 集羣方面進行重大改進。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們的託管雲服務使用 Kubernetes(K8s)來操作無服務器集羣,包括共享存儲節點和每租戶的 SQL 節點。每一個節點都運行在自己的 K8s pod 中,它就是一個帶有虛擬化網絡的 Docker 容器,並且 CPU 和內存容量有限。在深入研究之後,你將找到一個 Linux cgroup,可以可靠地限制進程的 CPU 和內存消耗。這樣,我們就可以根據每個租戶方便地測量和限制 SQL 資源消耗。這也可以最大限度地減少同一機器上調度的 pod 之間的干擾,即使其他租戶正在運行繁重的工作負載,也可以爲每一個租戶提供高質量的體驗。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面是一個典型設置的高級(簡化)表示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/83\/83a8ed3524e7178948e7583005114592.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那些“代理 pod”在 K8s 集羣中的作用是什麼?結果發現它們非常有用:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它們可以讓很多租戶共享同一個 IP 地址。在出現新的連接時,代理“嗅探”傳入的 Postgres 連接數據包,在 PG 連接選項中查找租戶標識符。這一步已經知道應該將這個連接路由到哪個 SQL pod。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它們在租戶的可用 SQL pod 上平衡負載。向 CPU 負載最小的 pod 發送新的連接。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它們檢測並應對涉嫌濫用服務的情況。這是我們爲保護你的數據而採取的安全措施之一。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當雲負載均衡器將一個新的連接路由到其中某個代理 pod 之後,代理 pod 又會將這個連接轉發到連接租戶所有的 SQL pod。每一個 SQL pod 只能提供一個租戶專用,而同一個租戶可以擁有多個 SQL pod。除非 SQL pod 屬於同一個租戶,否則網絡安全規則禁止彼此對話。最終,SQL pod 通過鍵值層通信來訪問共享存儲 pod 管理的數據,每個 pod 都將數據存儲在雲提供商的塊存儲系統中,例如 AWS EBS 或 GCP PD。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除創建速度外,無服務器 SQL pod 在成本方面也有巨大優勢。它們可以“擠”在一個虛擬機上,共享同一個操作系統,以及可用的 CPU 和內存。這樣做可以顯著地降低運行工作負載很小的“長尾”租戶的成本,因爲每個租戶都能使用一小塊硬件。相對於一個專用虛擬機來說,它通常需要至少保留一個 vCPU 和 1GB 的內存。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"擴展"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於租戶擁有的數據量越來越大,並且越來越頻繁地訪問這些數據,租戶的數據將被分割爲越來越多的鍵值範圍,這些鍵值範圍將被分散到更多的共享存儲 pod。CockroachDB 已經很好地支持了這種數據擴展,並且在多租戶集羣中的操作方式與在單租戶集羣中的操作方式基本相同。由於篇幅有限,我將不再贅述。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣,隨着針對租戶數據運行的 SQL 查詢和事務數量的增加,分配給該租戶的計算資源必須以一定比例增長。某個租戶的工作負載可能需要幾十個甚至幾百個 vCPU 來執行,而另一個租戶的工作負載可能只需要一個 vCPU 的部分時間。實際上,我們希望大多數租戶都不需要任何 CPU。這是因爲大部分嘗試 CockroachDB Serverless 的開發者只是在購買之前仔細權衡。他們會創建一個集羣,也許會對它進行一些查詢,然後放棄,很可能就是永遠的放棄。即使是爲他們的集羣保持一小部分 vCPU 的空閒,如果加上所有不活動的集羣,則會造成巨大的資源浪費。甚至對於經常使用集羣的租戶,SQL 流量負載也不穩定;它可能每天、每小時、甚至每秒波動很大。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"CockroachDB 無服務器是如何應對大量資源需求變化?基於每個租戶的每秒流量負載動態分配 SQL pod 的適當數量。最佳情況下,可立即分配新容量,而最壞的情況則可在數秒內分配。同時,還可以通過低延遲的方式平穩地處理租戶流量高峯。類似地,當通信量下降時,SQL 處理能力可以重新分配到其他地方,從而擁有最小的未使用能力。當流量降到零時,一個非活動租戶擁有的所有 SQL pod 將被終止,新的 SQL pod 在新的流量到達時將在幾百毫秒內重新啓動。這樣,很少被使用的 CockroachDB 無服務器集羣仍然能夠提供生產級延遲,而且對於 CockroachDB Labs 和用戶也不會帶來任何成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多租戶 CockroachDB 將 SQL 層與鍵值存儲層分割開來,這樣的響應式擴展才有可能。由於 SQL pod 是無狀態的,因此可以任意創建和銷燬,而不會影響租戶數據的一致性和持久性。無需在 pod 之間進行復雜的協調,也無需對有狀態存儲 pod 進行仔細的調試並退出,以確保所有數據都是一致且可用的。與通常保持長時間運行的存儲 pod 不同,SQL pod 是短暫的,可能在啓動後幾分鐘內就被關閉了。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Autoscaler"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在,我們再進一步看看擴展的機制。在每個無服務器集羣中,都有一個 Autoscaler 組件,負責確定分配給每個租戶的 SQL pod 的理想數量,無論是一個、多個還是零。Autoscaler 監控集羣中每個 SQL pod 的 CPU 負載,並根據兩個指標來計算 SQL pod 的數量:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最近 5 分鐘內的平均 CPU 使用率。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最近 5 分鐘內的 CPU 使用峯值。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 SQL pod 中,平均 CPU 使用率決定分配給租戶的“基線”數量。基線有意超額配置 SQL pod,這樣每個 pod 都有空餘的 CPU 可供即時突發。但是,如果最近的 CPU 使用峯值甚至超過了較高的超額配置閾值,那麼 Autoscaler 可以通過增加 SQL pod 超出基線的數量來解決這個問題。這種算法結合了移動平均數的穩定性和瞬時最大值的響應能力。Autoscaler 避免過度頻繁的擴展,但是仍然能夠快速地檢測和處理負載的巨大峯值。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 Autoscaler 得出 SQL pod 的理想數量時,它將觸發一個 K8s 調整過程,增加或刪除 pod,以達到理想數量。下圖顯示了可能的結果:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d0\/d0a8e0d8b844a06c8a5826bfac624ac2.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如圖所示,我們維護了一個“預熱”的 pod 池,這些 pod 隨時可以使用;它們只需要使用租戶的標識符和安全證書 “蓋戳”。這個過程僅需幾分之一秒的時間,而 K8s 從頭開始創建一個 pod 需要 20~30 秒。如果需要移除 pod,它們不會被突然終止,因爲這也會導致對該 pod 的所有 SQL 連接的粗暴終止。相反,pod 會被放置到“耗盡”(draining)狀態,這爲它們提供了更好地放棄 SQL 連接的機會。一旦所有的連接都消失了,或者 10 分鐘過去了,以先到者爲準,一個耗盡的 pod 將終止。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當應用負載降至零時, Autoscaler 最終決定暫停租戶,這意味着將刪除其所有 SQL pod。如果租戶不再擁有任何 SQL pod,它將不會消耗任何 CPU、 I\/O 或帶寬。惟一的成本就是它的數據存儲空間,與其他資源相比,它是相對便宜的。這也是我們可以爲大家提供免費數據庫集羣的原因之一。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,還有一個問題有待解決。在未爲租戶分配 SQL pod 的情況下,租戶如何連接集羣?要回答這個問題,請記住每個無服務器集羣都有一組代理 pod 正在運行。每一個由外部客戶機發起的 SQL 連接都被代理 pod 截獲,然後轉發到分配給租戶的 SQL pod。但是,如果代理髮現當前沒有爲租戶分配任何 SQL pod,它將觸發與 Autoscaler 所使用的相同的 K8s 調整過程。從預熱的 SQL pod 池中提取出一個新的 pod,並蓋上戳,現在可以用於連接。整個恢復過程只需要幾分之一秒,而我們正積極地努力使這個時間更短。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"結論"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然您瞭解了 CockroachDB 無服務器的工作原理,我鼓勵你訪問 "},{"type":"link","attrs":{"href":"https:\/\/cockroachlabs.cloud\/","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/cockroachlabs.cloud"}]},{"type":"text","text":" 並嘗試一下。如有任何疑問,請加入我們的"},{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/join-community\/","title":null,"type":null},"content":[{"type":"text","text":"社區 Slack 頻道"}]},{"type":"text","text":",提出問題。我還想聽聽你關於 CockroachDB 沒有服務器的經驗和反饋。在接下來的幾個月裏,我們會努力改進它。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"其他資源"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"免費的在線課程:"},{"type":"link","attrs":{"href":"https:\/\/university.cockroachlabs.com\/courses\/intro-to-serverless\/?referralId=andykblog","title":null,"type":null},"content":[{"type":"text","text":"無服務器數據庫和 CockroachDB 無服務器簡介"}]},{"type":"text","text":"("},{"type":"text","marks":[{"type":"italic"}],"text":"Introduction to Serverless Databases and CockroachDB Serverless"},{"type":"text","text":")。本課程介紹了無服務器數據庫背後的核心概念,並提供必要的工具來開始使用 CockroachDB 無服務器。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/www.cockroachlabs.com\/blog\/how-we-built-cockroachdb-serverless\/","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/www.cockroachlabs.com\/blog\/how-we-built-cockroachdb-serverless\/"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章