如何停止擔憂並開始沒有巨石的生活

如何停止擔憂並開始沒有巨石的生活

我們都喜歡故事。 我們喜歡坐在火邊談論我們過去的勝利、戰鬥,或只是我們的工作經驗。

今天就是這樣的一天。 即使您現在不在火場,我們也有一個故事給您。 我們如何開始在 Tarantool 上使用儲存的故事。

曾幾何時,我們公司有幾塊“巨石”和一個“天花板”,這些巨石正在緩慢而堅定地逼近,限制了我們公司的飛行和發展。 我們有一個清晰的認知:有一天我們會嚴重觸及這個上限。

現在流行的意識形態是從設備到業務邏輯,將一切和每個人分開。 因此,例如,我們有兩個在網路層級實際上獨立的 DC。 然後一切就完全不同了。

如今,有許多以 CI/CD、K8S 等形式進行變革的工具和工具。 在「鐵板一塊」的時代,我們不需要那麼多外來語。 只需更正資料庫中的「儲存」就足夠了。

但隨著時間的推移,請求的數量也隨之增加,有時 RPS 超出了我們的能力。 隨著獨聯體國家進入市場,第一塊巨石的資料庫處理器負載沒有降到90%以下,RPS保持在2400的水平。而且這些不僅僅是小選擇器,而是大量的查詢。一堆檢查和JOIN 可以在大IO 的背景下運行幾乎一半的資料。

當全面的黑色星期五促銷活動開始出現時——而 Wildberry 是最早在俄羅斯舉辦促銷活動的公司之一——情況變得非常糟糕。 畢竟這樣的日子負載量會增加三倍。
哦,這個「單一時代」! 我相信你也經歷過類似的事情,但你還是無法理解為什麼這種事會發生在你身上。

你能做什麼——時尚是科技所固有的。 大約 5 年前,我們必須以 .NET 和 MS SQL Server 上現有網站的形式重新考慮這些 mod 之一,該網站仔細儲存了網站本身的所有邏輯。 我小心翼翼地保存著它,以至於鋸開這樣一塊巨石變成了一種漫長而不易的樂趣。
一個小題外話。

在各種活動中我都會說:“如果你沒有看到一塊巨石,那麼你就沒有成長!” 我很想知道你對此事的看法,請寫在評論中。

一聲雷鳴

讓我們回到我們的「篝火」。 為了分配「整體」功能的負載,我們決定將系統劃分為基於開源技術的微服務。 因為,至少,它們的擴充成本更便宜。 我們 100% 理解我們必須擴大規模(而且規模很大)。 畢竟,那時就已經可以進入鄰國的市場,並且註冊數量以及訂單數量開始更加強勁地增長。

在分析了從單體架構轉向微服務的第一批候選人之後,我們意識到其中 80% 的編寫來自後台系統,而讀取來自前台系統。 首先,這涉及到我們的幾個重要子系統——用戶資料和基於額外客戶折扣和優惠券資訊計算商品最終成本的系統。

縮排。 現在想像起來很可怕,但除了上述子系統之外,產品目錄、用戶購物車、產品搜尋系統、產品目錄過濾系統和各種推薦系統也從我們的整體中刪除了。 對於它們每個人的操作,都有不同類別的狹隘定制系統,但曾幾何時,它們都住在一個“房子”裡。

我們立即計劃將客戶的資料傳輸到分片系統。 取消計算商品最終成本的功能需要良好的讀取擴展性,因為它產生的RPS負載最大,並且對資料庫來說最難實現(計算過程中涉及大量資料)。

結果,我們想出了一個非常適合 Tarantool 的方案。

當時對於微服務的運行,選擇了在虛擬機器和硬體機上與多個資料中心配合的方案。 如圖所示,Tarantool 複製選項適用於主-主和主-從模式。

如何停止擔憂並開始沒有巨石的生活
建築學。 選項 1. 用戶服務

目前有24個分片,每個分片有2個實例(每個DC一個),都是master-master模式。

資料庫之上是存取資料庫副本的應用程式。 應用程式透過我們的自訂程式庫與 Tarantool 配合使用,該程式庫實作了 Tarantool Go 驅動程式介面。 她可以看到所有副本,並且可以與主副本一起讀寫。 本質上,它實現了副本集模型,並添加了用於選擇副本、執行重試、斷路器和速率限制的邏輯。

在這種情況下,可以在分片的上下文中設定副本選擇策略。 例如,循環賽。

如何停止擔憂並開始沒有巨石的生活
建築學。 選項 2. 計算貨物最終成本的服務

幾個月前,大多數計算商品最終成本的請求都發送給了一項新服務,該服務原則上無需資料庫即可運行,但不久前,所有內容都由 Tarantool 底層的服務 100% 處理。

服務資料庫由 4 個主站組成,同步器將資料收集到其中,每個複製主站將資料分發到唯讀副本。 每個主節點大約有 15 個這樣的副本。

無論在第一種方案或第二種方案中,如果一個DC不可用,應用程式可以在第二個DC中接收資料。

值得注意的是,Tarantool 中的複製非常靈活,可以在運行時進行配置。 在其他系統中,出現了困難。 例如,變更 PostgreSQL 中的 max_wal_senders 和 max_replication_slots 參數需要重新啟動精靈,這在某些情況下可能會導致應用程式和 DBMS 之間的連線中斷。

尋找,你就會找到!

為什麼我們不「像正常人一樣」去做,而是選擇了一種非典型的方式? 這取決於什麼被認為是正常的。 許多人通常從 Mongo 建立一個群集並將其分佈在三個地理分佈式 DC 上。

當時我們已經有兩個Redis項目了。 第一個是緩存,第二個是用於不太關鍵資料的持久性儲存。 他的處境相當困難,部分原因是我們的錯。 有時,關鍵的體積很大,而且該網站有時會變得不舒服。 我們在主從版本中使用了這個系統。 而且有很多情況是master出了問題導致複製崩潰的。

也就是說,Redis 適合無狀態任務,而不適合有狀態任務。 原則上,它可以解決大多數問題,但前提是它們是具有一對索引的鍵值解決方案。 但當時的Redis在持久化和複製上是相當可悲的。 此外,還有關於性能的抱怨。

我們考慮了 MySQL 和 PostgreSQL。 但第一個產品不知為何沒有引起我們的注意,而第二個產品本身就是一個相當複雜的產品,在其上建立簡單的服務是不合適的。
我們嘗試了 RIAK、Cassandra,甚至是圖形資料庫。 這些都是相當小眾的解決方案,不適合作為創建服務的通用工具。

最終我們選擇了 Tarantool。

我們在 1.6 版本時轉向了它。 我們對它感興趣的是鍵值對和關係資料庫功能的共生。 還有二級索引、事務和空間,這些就像表一樣,但並不簡單,你可以在其中儲存不同數量的列。 但 Tarantool 的殺手級功能是與鍵值和事務性結合的二級索引。

反應靈敏、隨時準備在聊天中提供幫助的俄語社群也發揮了作用。 我們積極使用這一點並直接在聊天中進行直播。 並且不要忘記體面的堅持,沒有明顯的失誤和錯誤。 如果你看看我們使用 Tarantool 的歷史,我們在複製方面遇到了很多痛苦和失敗,但我們從未因為它的錯誤而丟失資料!

實施起步艱難

當時,我們主要的開發堆疊是 .NET,Tarantool 沒有連接器。 我們立即開始用 Go 做一些事情。 它與 Lua 也運作良好。 當時的主要問題是調試:在 .NET 中一切都很好,但之後就很難投入嵌入式 Lua 的世界了,因為除了日誌之外沒有任何調試。 此外,由於某種原因,複製會定期崩潰,因此我必須深入研究 Tarantool 引擎的結構。 聊天對此有所幫助,在較小程度上,文件也有所幫助;有時我們會查看程式碼。 那時,文檔馬馬虎虎。

因此,在幾個月的時間裡,我設法頭腦清醒,並透過與 Tarantool 的合作獲得了不錯的結果。 我們編譯了 git 的參考開發,有助於形成新的微服務。 例如,當出現一個任務:建立另一個微服務時,開發人員查看儲存庫中參考解決方案的原始程式碼,只花了不到一周的時間就創建了一個新的微服務。

這是一段特殊的時期。 按照慣例,你可以去找鄰桌的管理員詢問:“給我一個虛擬機。” 大約三十分鐘後,車子就到了。 您自己連接,安裝了所有內容,然後流量就發送給您了。

如今,這將不再有效:您需要為服務添加監控和日誌記錄、透過測試覆蓋功能、訂購虛擬機器或交付給 Kuber 等。 一般來說,這樣會比較好,雖然時間會比較長,也比較麻煩。

分而治之。 和Lua有什麼關係?

存在一個嚴重的困境:一些團隊無法可靠地推出 Lua 中包含大量邏輯的服務的更改。 這通常伴隨著服務不起作用。

也就是說,開發者正在準備某種改變。 Tarantool 開始進行遷移,但副本仍使用舊程式碼; 一些 DDL 或其他東西透過複製到達那裡,程式碼就會崩潰,因為它沒有被考慮在內。 結果,管理員的更新流程就寫在A4紙上:停止複製,更新這個,打開複製,這裡關閉,那裡更新。 惡夢!

因此,現在我們通常嘗試在 Lua 中什麼都不做。 只需使用 iproto(一種用於與伺服器互動的二進位協定)即可。 也許這是開發人員缺乏知識的原因,但從這個角度來看系統是複雜的。

我們並不總是盲目地遵循這個腳本。 今天我們沒有黑白分明:要么一切都在 Lua 中,要么一切都在 Go 中。 我們已經了解如何將它們結合起來,這樣我們就不會在以後出現遷移問題。

塔蘭圖爾現在在哪裡?
在該服務中使用 Tarantool 計算商品的最終成本,並考慮折扣優惠券(也稱為「Promoter」)。 正如我之前所說,他現在即將退休:他將被一項預先計算價格的新目錄服務所取代,但六個月前所有計算都是在 Promotizer 中進行的。 此前,其一半邏輯是用Lua編寫的。 兩年前,該服務被變成了一個儲存設施,並且用 Go 重寫了邏輯,因為折扣機制發生了一些變化,而該服務缺乏效能。

最關鍵的服務之一是使用者設定檔。 也就是說,所有的Wildberry用戶都儲存在Tarantool中,大約有50萬個,依照用戶ID進行分片的系統,分佈在連接Go服務的多個DC上。
根據 RPS 的數據,Promoter 曾經是領先者,達到了 6 個請求。 一度我們有 50-60 份。 現在RPS的領導者是用戶個人資料,大約有12萬個。該服務使用自訂分片,依照用戶ID的範圍進行劃分。 該服務服務於20多台機器,但這太多了;我們計劃減少分配的資源,因為4-5台機器的容量就足夠了。

會話服務是我們在 vshard 和 Cartridge 上的第一個服務。 設定 vshard 和更新 Cartridge 需要我們付出一些努力,但最終一切順利。

用於在網站和行動應用程式中顯示不同橫幅的服務是直接在 Tarantool 上發布的首批服務之一。 該服務值得注意的是,它已有 6-7 年歷史,仍在運行且從未重新啟動過。 使用了主主複製。 沒有任何東西被破壞過。

有一個在倉庫系統中使用 Tarantool 進行快速參考功能的範例,以便在某些情況下快速複核資訊。 我們嘗試使用 Redis 來實現此目的,但記憶體中的資料比 Tarantool 佔用更多空間。

Tarantool 還提供候補名單、客戶訂閱、當前流行故事和延期商品等服務。 最後一個服務佔用記憶體約120GB。 這是上述服務中最全面的服務。

結論

由於二級索引與鍵值和事務性相結合,Tarantool 非常適合基於微服務的架構。 然而,當我們對 Lua 中包含大量邏輯的服務進行更改時,我們遇到了困難 - 服務經常停止工作。 我們無法克服這個問題,隨著時間的推移,我們找到了 Lua 和 Go 的不同組合:我們知道在哪裡使用一種語言,在哪裡使用另一種語言。

關於該主題還可以閱讀什麼

來源: www.habr.com

添加評論