3C科技 娛樂遊戲 美食旅遊 時尚美妝 親子育兒 生活休閒 金融理財 健康運動 寰宇綜合

Zi 字媒體

2017-07-25T20:27:27+00:00
加入好友
作者|Venkatesh Ramaswamy編輯|麥克周eBay 的員工 Venkatesh Ramaswamy 於 2017 年 1 月發表了一篇文章,文章發表在 eBay 技術博客上,文章主要講了針對購物車緩存數據丟失情況,eBay 思考的三種解決方案,以及最終採用的解決方案。背景 eBay 的購物車信息存儲依賴於兩個不同的數據存儲介質,MongoDB 存儲用戶完整的購物車信息,Oracle 僅存儲購物車的大致信息,但是可以通過關鍵信息查找所有的購物車信息。在 eBay 的這套系統里,MongoDB 更多被用來充當「緩存」,Oracle 資料庫作為存儲副本。如果數據在 MongoDB 裡面找不到了,服務會從 Oracle 裡面重新抽取(恢復)數據,然後重新計算用戶的購物車。所有的購物車數據都是 JSON 格式的,JSON 數據在 Oracle 里被存儲在 BLOB 格式的欄位里。這些 Oracle 裡面的數據只能被用於 OLTP 交易。這篇文章並不是討論資料庫技術的選擇(Oracle vs MongoDB,或者其他數據),而是希望能夠讓大家在巨量訪問系統(每天上百萬次調用)中找到技術債,理解如何解決問題。問題描述 2016 年秋天開始,購物車服務出現了緩存層丟失數據的情況,同時,運維團隊報告 MongoDB 的備份機制多次出現失敗(MongoDB 運行在主從模式)。eBay 的這個服務已經運行了 5 年時間,一直沒有出現問題,沒有做過任何架構調整和大規模代碼改變,需要儘快找到原因和防治辦法。針對實際問題進行反覆檢查,發現 MongoDB 的 oplog(實時性要求極高的寫日誌記錄)正在達到網路 I/O 限制。每一次的數據丟失,都會觸發保護措施(再次從 Oracle 讀取數據后重複計算),並進一步加長用戶的等待時間。解決方案 在我們具體討論特定的解決方案前,我們希望去儘可能多地討論解決方案。例如,一旦備份機制沒有啟用,是否可以通過隱藏一些副本方式讓系統能夠正常運行,而不要在系統特別繁忙的時候去嘗試重新備份。我們可以嘗試超時機制和階段性副本方式,但是這些方式並不會引起我們本文說的問題發生。方案一:切片(MongoDB)團隊成員提出對 JSON 數據進行切分,即對原先存儲在 MongoDB 里的原子化的購物車信息(一個 JSON 字元串),切分為多個字元串,這樣做的好處是可以減少單一 MongoDB 中心節點的寫入次數和網路開銷。對於數據切分后的關聯方式,遠比數據切分、負載均衡複雜,因此,第 1 種方案的選擇會引入其他技術難點,需要我們自己能夠尋找被切分后的數據的關聯性,這就是為什麼 eBay 放棄了這個方案。方案二:有選擇的寫入使用 MongoDB 的 set 命令,只針對當特定值發生更改后,才啟動寫入操作。這種方式理論上也是可行的。但是如果你真正考慮一下,這種做法沒有從根本上確保減少 oplogs 寫入次數,但是它很有可能會造成整個文檔的更新。了解一下 MongoDB 的 Set 操作模式。Set 操作可以用於使用特定值替換欄位值:{$Set{:,…}}假如你考慮一下描述產品的文檔如下所示:{ _id:100, sku:」abc123」, quantity:250, instck:true, reorder:false, details:{model:」14Q2」,make:」xyz」}, tags:[「appeal」,」clothing」], ratings:[{by:」ijk」,rating:4}] }對於滿足 _id 等於 100 的文檔,執行 set 操作更新 quantity 欄位、details 欄位和 tags 欄位的值。db.products.update( {_id:100}, {$set: { quantity:500, details:{model:」14Q3」,make:」xyz」}, tags:[「coats」,」outerwear」,」clothing」] } } )以上這個操作替換 quantity 的值為 500,details 欄位的值為一個新的嵌入式文檔,tags 值為一個數組。方案三:壓縮傳輸數據考慮到需要儘快解決問題,所以需要盡量避免重寫業務邏輯,壓縮方式看起來是比較好的一中了。減少進入 MongoDB 的 Master 節點的數據量,這樣可以減少寫入 oplog 的數據規模。但是,這種方式會將 JSON 字元串轉變為二進位文章,操作時也需要解壓縮。常用的壓縮演算法主要有:deflate、gzip、bzip2、lzo、snappy 等。差別如下所示:deflate、gzip 都是基於 LZ77 演算法與哈夫曼編碼的無損數據壓縮演算法,gzip 只是在 deflate 格式上增加了文件頭和文件尾;bzip2 是 Julian Seward 開發並按照自由軟體 / 開源軟體協議發布的數據壓縮演算法,Apache 的 Commons-compress 庫中進行了實現;LZO 致力於解壓速度,並且該演算法也是無損演算法;LZ4 是一種無損數據壓縮演算法,著重於壓縮和解壓縮速度;Snappy 是 Google 基於 LZ77 的思路用 C++ 語言編寫的快速數據壓縮與解壓程序庫,2011 年開源。它的目標並非最大程度地壓縮,而是針對最快速度和合理的壓縮率。目標和考慮在我們開始做這一功能性測試之前,我們需要明確幾個目標。允許購物車被壓縮並持久化到 MongoDB(數據不會有改變)。允許壓縮編碼方式的選擇,支持採用一種編碼方式讀取,另一種編碼方式寫入。允許讀到老的、新的、中間狀態的購物車信息,新老前後可以互相兼容。壓縮和解壓縮的操作可以同時進行。確保沒有針對 MongoDB 資料庫的實時 JSON 數據檢索查詢請求。JSON 字元串例子這是老的 JSON 字元串:{ "_id" : ObjectId("560ae017a054fc715524e27a"), "user" : "9999999999", "site" : 0, "computeMethod" : "CCS_V4.0.0", "cart" : "...JSON cart object...", "lastUpdatedDate" : ISODate("2016-09-03T00:47:44.406Z") }這是壓縮之後的 JSON 字元串:{ "_id" : ObjectId("560ae017a054fc715524e27a"), "user" : "9999999999", "site" : 0, "computeMethod" : "CCS_V4.0.0", "cart" : "...JSON cart object...", "compressedData" : { "compressedCart" : "...Compressed cart object..." "compressionMetadata" : { "codec" : "LZ4_HIGH", "compressedSize" : 3095, "uncompressedSize" : 6485 }, }, "lastUpdatedDate" : ISODate("2016-09-03T00:47:44.406Z") }測試結果通過使用相同的購物車數據進行測試,觀察 CPU 或者 I/O 情況,數據如圖所示:結論oplog 的寫入速率,從 150GB/ 小時下降為大約 11GB/ 小時,下降了 1300%!文檔的平均對象大小從 32KB 下降為 5KB,600% 的下降。此外,服務的響應時間也有所改善。數據如圖所示:下面這張圖顯示的是 MongoDB 的 Ops Manager UI 工具信息,特別標註了壓縮和解壓縮數據的耗時,以及文檔的平均對象大小的下降數據。最終,對於生產環境下的隨機一小時數據壓縮,eBay 團隊也收集了一些指標圖,用於更多的深入觀察。2017 年 8 月 10-11 日,聽雲聯合極客邦科技、InfoQ 將共同主辦國內第二屆應用性能管理大會 -APMCon 2017,會議的演講內容聚焦行業內最新的技術和最接地氣的實踐案例,共同探討 APM 相關的性能優化、技術方案以及創新思路,為更多的行業從業者指點應用效能提升的迷津。為回饋 InfoQ 讀者,特奉上優惠碼:APMCon_0810,立減 99 元!進入大會官網 www.apmcon.cn,了解更多專家信息吧!

本文由yidianzixun提供 原文連結

寫了 5860316篇文章,獲得 23313次喜歡
精彩推薦