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