松花皮蛋的黑板報
  • 分享在京東工作的技術感悟,還有JAVA技術和業內最佳實踐,大部分都是務實的、能看懂的、可復現的

掃一掃
關注公眾號

談談數據異構

博客首頁文章列表 松花皮蛋me 2019-11-10 09:29

京東的內容創作平臺有很多的樣式,比如文章、單品推薦、搭配、店鋪上新、秒殺、直播預告、優惠卷。有些樣式可以投稿到不同的頻道,頻道就好比露出的位置,頻道露出的前提是內容質量審核通過后,頻道側二審通過。上面列舉的有些樣式因為時效性的考慮所以是不需要審核就可以外露的,比如直播預告、優惠卷,其他的樣式則需要在CMS后臺管理中經過一道或者兩道審核,或者在質檢抽查中復活。


我們知道內容體裁類都是讀多寫少的,所以一般強依賴緩存。其中,剛剛提到的很多場景都會直接寫緩存或更新緩存,比如有些內容不需要審核、內容審核一次后、內容審核兩次后、內容編輯后、內容編輯標簽后、內容定時上下線等等,那么就需要有一個組件化的服務來滿足同步。如果由你來設計一種方案來同步緩存或者多級緩存,你會怎么做呢?這就是我今天要和大家討論的數據異構,將數據進行異地異構存儲,比如說需要整合多張表數據構成一條記錄然后異地存儲。


我們先來看下第一種方案,就是雙寫,業務代碼在對數據庫操作時同步緩存。不過用這種對業務侵入的硬編碼方式有很多缺點,我們首先得考慮事務性,考慮怎么保證同步數據庫和同步緩存兩者要么都成功要么都失敗,但是一旦使用上事務,性能下降會非常明顯。你可能看到過這種方案,更新操作時,先刪除緩存后更新數據庫,讓查詢操作來同步刷數據到緩存,這種方案最大的問題就是如果你刪除的緩存是熱點數據,那將導致大量的請求直接達到數據庫。更極端的情況是,更新操作時,緩存節點不可用、程序和緩存節點之間網絡延時增高、程序重啟來不及同步緩存節點,那就會導致服務性能受到影響、數據無法達到一致性。


剛剛的雙寫是同步進行,如果換成使用MQ異步雙寫呢?也就是,程序處理完業務邏輯后發送MQ事件通知,由不同的應用消費MQ然后分別寫入數據庫和緩存中,其中寫緩存的應用再反查其他表。很明顯,異步雙寫的方案比前面的簡單雙寫性能肯定高很多,甚至我們還可以利用MQ的重試機制保證數據不丟失。不過它依然存在硬編碼、與業務強耦合的問題,還引入了時延問題。因為有些MQ消息必須是串行處理的,或者由于網絡原因導致無法及時被消費,就會導致操作結果不一定能馬上看到。


那我們再來看下第三種方案,使用定時任務異步雙寫。數據表中增加一個時間標示的字段,任何更新操作都導致該字段的值發生變化。然后增加一個定時器程序,每隔一段時間掃描表,把該時間段內發生變化的數據提取出來,然后逐條同步到緩存中。不過這種方式對數據庫有很大的輪詢壓力,所以一般都不采用這種方式。


那有沒有更好的方案完成數據異構呢?答案就是利用Mysql的binlog日記。


Mysql的binlog日記主要用來記錄對mysql數據更新的操作,并以事務的形式保存在磁盤中,一般用來做Mysql的主從復制、數據恢復、增量備份。可以看出binlog日記具備高可靠性、低時延性,所以我們可以利用binlog日記來完成數據異構。整體流程大概是這樣的,構建一個中間件系統,偽造成master的一個slave,當讀取到binglog中的數據變化后,將其二進制內容格式化成MQ消息后傳輸,程序拿到消息后同步緩存。不過缺點也很明顯,需要有一個中間件系統支撐,如果沒有的話,使用前面提到的MQ異步雙寫或許是最佳的選擇。


好,今天我主要和你討論了關于如何利用數據異構實現多級緩存,這個技術還可以解決下面這種問題,比如數據庫分庫分表后如何進行數據遷移,當然后者的實現更加復雜,需要考慮數據校驗問題,就不再展開了。如果今天的文章有幫助到你,歡迎分享給你朋友或者點個在看。

黑龙江6+1开奖结果查询