基于redis分布式緩存實現

jopen 11年前發布 | 62K 次閱讀 Redis NoSQL數據庫

一.為什么選擇redis

在項目中使用redis做為緩存,還沒有使用memcache,考慮因素主要有兩點:

1.redis豐富的數據結構,其hash,list,set以及功能豐富的String的支持,對于實際項目中的使用有很大的幫忙。(可參考官網redis.io)

2.redis單點的性能也非常高效(利用項目中的數據測試優于memcache).

基于以上考慮,因此選用了redis來做為緩存應用。

二.分布式緩存的架構設計

1.架構設計

由于redis是單點,項目中需要使用,必須自己實現分布式。基本架構圖如下所示:
1353157057_4142.png
2.分布式實現

通過key做一致性哈希,實現key對應redis結點的分布。

一致性哈希的實現:

l hash值計算:通過支持MD5與MurmurHash兩種計算方式,默認是采用MurmurHash,高效的hash計算。

l 一致性的實現:通過java的TreeMap來模擬環狀結構,實現均勻分布

3.client的選擇

對于jedis修改的主要是分區模塊的修改,使其支持了跟據BufferKey進行分區,跟據不同的redis結點信息,可以初始化不同的 ShardInfo,同時也修改了JedisPool的底層實現,使其連接pool池支持跟據key,value的構造方法,跟據不同 ShardInfos,創建不同的jedis連接客戶端,達到分區的效果,供應用層調用

4.模塊的說明

l 臟數據處理模塊,處理失敗執行的緩存操作。

l 屏蔽監控模塊,對于jedis操作的異常監控,當某結點出現異常可控制redis結點的切除等操作。

整個分布式模塊通過hornetq,來切除異常redis結點。對于新結點的增加,也可以通過reload方法實現增加。(此模塊對于新增結點也可以很方便實現)

對于以上分布式架構的實現滿足了項目的需求。另外使用中對于一些比較重要用途的緩存數據可以單獨設置一些redis結點,設定特定的優先級。另外對 于緩存接口的設計,也可以跟據需求,實現基本接口與一些特殊邏輯接口。對于cas相關操作,以及一些事物操作可以通過其watch機制來實現。(參考我以 前寫的redis事物介紹)

以上是基于redis分布式架構的介紹!但是應用中讀寫都是在一起的。相關寫是在應用操作后flush或者update的,有一定的耦合。為了使讀 寫分離,以及緩存模塊跟應用的耦合更小,考慮使用mysql binlog來刷新緩存。以下是基于binlog刷新可性行分析以及實現過程中需要注意的地方。

三.采用binlog架構刷新緩存可行性分析
1.Mysql日志格式介紹可參考我以前的的介紹。

2.對于使用MIXED日志格式,此日志格式,記錄的是對應數據庫操作的SQL語句,采用此日志方式存在的問題:

l 對于一些未任何更新操作的SQl語句,像條件不滿足,對應的sql也會記錄到binlog日志中。

l SQL語句記錄的未必包括所有的更新操作。

l 對于一些分布式數據庫,對于SQL中的where條件指定的是非均衡字段,也許會存在多條SQL,跟設計有關!

基于以上考慮,采用MIXED的日志格式進行binlog解析是行不通的。(官網給出的指示是failed statementsare not logged ,但不包括語法沒錯誤,更新條件不符合對應的SQL)

3.采用ROW日志格式

對于此日志格式,每行變化都有對應的記錄,此日志格式,對于解析及采集數據都是非常方便的,也只有采用此日志格式,才能基于binlog修改,做刷新緩存相關方案的設計。但是基于此日志格式也存在一些問題:

l 需要考慮項目中是否有大量的批量的update操作,如果采用此日志格式,批量操作每一行修改都會記錄一條日志,大量的批量操作所產生的日志量,以及所帶來的IO開銷是否可以接受。

通過以上分析,最終項目中還是考慮基于ROW日志格式進行緩存刷新,還有一個問題需要考慮,在應用層DB進行了相應的update操作后,所產生的 Binlog是會帶來一定的延遲,如果Binlog處理模塊正常運行,數據是的延遲會非常少,MS級別以內,對用戶體驗是沒有感知的,但是Binlog模 塊是多點,異常,以及相應的延遲肯定會是存在的,這樣,緩存數據肯定會存在臟數據。

不過通過以上方案,數據能達到最終一致性,因此how to權衡,需要考慮。

通過以上分析,是否采用Binlog來做緩存數據刷新相信大家有一個基本概念了

四.基于binlog刷新緩存的實現時注意的地方

1.如果是采用java做相關開發,可以使用開源的tungstenAPI

2.Binlog日志解析是按照mysql 的master/slave同步流程來實現,即一個線程同步,一個線程解析。

3.設計是可分Binlog處理模塊以及緩存處理SqlEvent兩部分,其中Binlog處理解析好對應的SqlEvent,然后對應的緩存刷新處理SqlEvent,一個簡單的生產者-消費者模式。

4.對于多個Binlog處理模塊可以是單點,也可以是通過一些協同工具來管理,看需求。可以使用ZooKeeper等。

5.對于分布式緩存中的數據,對于Binlog來刷新的緩存數據會存在load數據的問題,為了減輕DB的額外壓力,flush操作可在get緩存數據處完成。看需求,如果讀寫完全分享的話此DB的額外壓力可以接收的話也可行。

6.對于緩存數據性一致性要求比較高的,可以通過版本號來控制,即在應用層引入一定的耦合,在DB操作時帶mark ,緩存刷新是也mark,另外get操作時比較雙版本號來達到數據的一致性。(此跟5談論的一定的聯系,讀寫是否完全分離,以及相應一致性實現的一些方法)

五.一點心得
前前后后,對redis完成調研,以及相關的一些使用,分布式緩存的實現,基于binlog方式的修改等,接觸有一年多了,這段時間下來,學了很多,以上算是一點小記,這部分工作的一點小記。實現過程中存在更多的問題。

對于調研相關的一些工作,一定要做的仔細,相應的細節一定要了解透徹,否則也許一此小問題會導致整個方案的不可行,甚至更大的的問題。連鎖反應!

</span>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!