阿里云分布式缓存OCS与DB之间的数据一致性
來源:http://www.csdn.net/article/1970-01-01/2825234
摘要:OCS是阿里巴巴集團的分布式緩存產品,支撐著淘寶、阿里巴巴、支付寶的日常運作,尤其在雙11等大型活動上,承載了絕大多數的數據請求。與OCS相比,著名的Memcached具備了分布式集群管理的功能。
OCS概要介紹
據AlertSite網絡分析公司表示,Facebook的響應時間在2010年平均為1秒鐘,到2011年中期已提高到了0.73秒。對比來看,響應時間占第二位的LinkedIn,網絡下載內容時要花費將近2倍的時間。Twitter的響應時間則整整遲了2秒鐘。響應時間優化的首要手段就是采用緩存技術,減少系統間交互請求和磁盤IO。
OCS是阿里巴巴集團的分布式緩存產品,支撐著淘寶、阿里巴巴、支付寶的日常運作,尤其在雙11等大型活動上,承載了絕大多數的數據請求。與OCS相比,著名的Memcached具備了分布式集群管理的功能。2014年OCS經歷了從分布式到云服務的進化,作為阿里云服務的緩存產品正式商業化。
OCS技術講解
OCS的核心存儲是淘寶的開源產品TAIR(發音:太愛兒)
TAIR原理
角色上分為DataServer,ConfigServer:
集群初始化時ConfigServer會根據DataServer的數量分配BucketID到DataServer上,這層映射關系就是數據路由索引,BucketID屬于[0-1023]的范圍內。客戶端第一次啟動時會從ConfigServer上拉取映射關系,之后的讀寫請求,根據全局約定的Hash算法(例如MurmurHash(key)24)計算出BucketID,根據映射關系描述向指定的DataServer上發送請求。
ConfigServer上的路由信息會根據DataServer存活狀況動態修改更新;新結果再告知給DataServer;當DataServer處理客戶端響應時,將變更通知給客戶端。
圖1 路由路徑
從TAIR到OCS
云服務化的過程中,首要問題是滿足用戶的兼容性需求,用戶訪問接口上支持廣泛流行的Memcached接口,原生于Memcached的應用,可以無縫遷移到OCS上來。
其次是穩定性,集群升級時,由于進程重啟會造成應用請求OCS瞬間報錯,OCS實現了一套熱升級方案,在保持TCP鏈接不中斷的情況下重啟進程。
云服務還有一個重要特性就是多租戶,多租戶的情況下,為了防止某一兩個用戶的高并發訪問造成集群負載上升,從而影響了其他租戶的穩定性。OCS內部對不同的租戶進行了資源隔離,針對請求量、帶寬、內存使用量做了嚴格的限制。不同規格的用戶可以購買不同規格的OCS實例,之間不會互相干擾。
與OCS相比,自建的Memcached解決了單機容量上線問題,實現擴容自動化且不需要修改客戶端配置,同時輸出了性能監控指標,網頁版Console命令等。
緩存失效一致性問題
一般緩存的使用方式是:先讀取緩存,若不存在則從DB中讀取,并將結果寫入到緩存中;下次數據讀取時便可以直接從緩存中獲取數據。
數據的修改是直接失效緩存數據,再修改DB內容,避免DB修改成功,但由于網絡或者其他問題導致緩存數據沒有清理,造成了臟數據。
但這樣仍然無法避免臟數據的產生,一種并發的場景下:假設業務對數據Key:Hello Value:World有大量的讀取和修改請求。線程A向OCS讀取Key:Hello,得到Not Found結果,開始向DB請求數據,得到數據Key:Hello Value:World;接下來準備向OCS寫入此條數據,但在寫入OCS前(網絡,CPU都等可能導致A線程處理速度降低)另一B線程請求修改數據Key:Hello Value:OCS,首先執行失效緩存動作(因為B線程并不知道是否有此條數據,因此直接執行失效操作),OCS成功處理了失效請求。轉回到A線程繼續執行寫入OCS,將Key:Hello Value:World寫入到緩存中,A線程任務結束;B線程也成功修改了DB數據內容為Key:Hello Value:OCS。
圖2 并發時序
此時OCS中的數據為Key:Hello Value:World;DB中的數據為Key:Hello Value:OCS,出現緩存臟數據!
為了解決這個問題,OCS擴充了Memcached協議(公有云即將支持),增加了deleteAndIncVersion接口。此接口并不會真的刪除數據,而是給數據打了標簽,表明已失效狀態,并且增加數據版本號;如果數據不存在則寫入NULL,同時也生成隨機數據版本號。OCS寫入支持原子對比版本號:假設傳入的版本號與OCS保存的數據版本號一致或者原數據不存在,則準許寫入,否則拒絕修改。
回到剛才的場景上:線程A向OCS讀取Key:Hello,得到Not Found結果,開始向DB請求數據,得到數據Key:Hello Value:World;接下來準備向OCS寫入此條數據,版本號信息默認為1;在A寫入OCS前另一個B線程發起了動作修改數據Key:Hello Value:OCS,首先執行刪除緩存動作,OCS順利處理了deleteAndIncVersion請求,生成了隨機版本號12345(約定大于1000)。轉回到A線程繼續執行寫入OCS,請求將Key:Hello Value:World寫入,此時緩存系統發現傳入的版本號信息不匹配(1?!=?12345),寫入失敗,A線程任務結束;B線程也成功修改了DB數據內容為Key:Hello Value:OCS。
此時OCS中的數據為Key:Hello Value:NULL Version:12345;DB中的數據為Key:Hello Value:OCS,后續讀任務時會再次嘗試將DB中的數據寫入到OCS中。
類似的并發場景還有很多,讀者可以自行推演,同時也可以思考下為何約定隨機生成的版本要大于1000?
緩存數據的同步的一致性問題
隨著網站規模增長和可靠性的提升,會面臨多IDC的部署,每個IDC都有一套獨立的DB和緩存系統,這時緩存一致性又成了突出的問題。
首先緩存系統為了保證高效率,會杜絕磁盤IO,哪怕是寫BINLOG;當然緩存系統為了性能可以只同步刪除,不同步寫入,那么緩存的同步一般會優先于DB同步到達(畢竟緩存系統的效率要高得多),那么就會出現緩存中無數據,DB中是舊數據的場景。此時,有業務請求數據,讀取緩存Not Found,從DB讀取并加載到緩存中的仍然是舊數據,DB數據同步到達時也只更新了DB,緩存臟數據無法被清除。
圖3 并發時序
從上面的情況可以看出,不一致的根本原因是異構系統之間無法協同同步,不能保證DB數據先同步,緩存數據后同步。所以就要考慮緩存系統如何等待DB同步,或者能否做到兩者共用一套同步機制?緩存同步也依賴DB BINLOG是一個可行的方案。
IDC1中的DB,通過BINLOG同步給IDC2中的DB,此事IDC2-DB數據修改也會產生自身的BINLOG,緩存的數據同步就可以通過IDC2-DB BINLOG進行。緩存同步模塊分析BINLOG后,失效相應的緩存Key,同步從并行改為串行,保證了先后順序。
這樣,IDC間的數據同步架構更加簡單清晰,系統服用率高,做好BINLOG同步和抓取即可。
圖4 異地同步
總結
不同系統之間的數據同步一直是一個世界性的問題,目前仍然沒有方法解除CAP魔咒,只能根據實際的情況在三者之間尋找理想的平衡點。本文介紹的解決方案,其一是利用了緩存系統的原子操作,其二是利用了外部系統同步機制保證先后,都是在犧牲最小的性能代價時獲取最大的一致性保證,但仍然無法覆蓋全部場景下的一致性問題。
與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
以上是生活随笔為你收集整理的阿里云分布式缓存OCS与DB之间的数据一致性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公交车站(说一说公交车站的简介)
- 下一篇: 微信web开发者工具调试