一.爲何選擇redisjava
在項目中使用redis作爲緩存,尚未使用memcache,考慮因素主要有兩點:mysql
1.redis豐富的數據結構,其hash,list,set以及功能豐富的String的支持,對於實際項目中的使用有很大的幫忙。(可參考官網redis.io)redis
2.redis單點的性能也很是高效(利用項目中的數據測試優於memcache).sql
基於以上考慮,所以選用了redis來作爲緩存應用。數據庫
二.分佈式緩存的架構設計緩存
1.架構設計數據結構
因爲redis是單點,項目中須要使用,必須本身實現分佈式。基本架構圖以下所示:
2.分佈式實現架構
經過key作一致性哈希,實現key對應redis結點的分佈。分佈式
一致性哈希的實現:ide
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方式的修改等,接觸有一年多了,這段時間下來,學了不少,以上算是一點小記,這部分工做的一點小記。實現過程當中存在更多的問題。
對於調研相關的一些工做,必定要作的仔細,相應的細節必定要了解透徹,不然也許一此小問題會致使整個方案的不可行,甚至更大的的問題。連鎖反應!