第一:Redis 是什麼?前端
Redis是基於內存、可持久化的日誌型、Key-Value數據庫 高性能存儲系統,並提供多種語言的API.java
第二:出現背景mysql
可靠性需求
Cache的"雪崩"問題讓人糾結
Cache面臨着快速恢復的挑戰redis
開發成本需求
Cache和DB的一致性維護成本愈來愈高(先清理DB, 再清理緩存, 不行啊, 太慢了!)
開發須要跟上不斷涌入的產品需求
硬件成本最貴的就是數據庫層面的機器,基本上比前端的機器要貴幾倍,主要是IO密集型,很耗硬件;sql
維護性複雜
一致性維護成本愈來愈高;
BerkeleyDB使用B樹,會一直寫新的,內部不會有文件從新組織;這樣會致使文件愈來愈大;大的時候須要進行文件歸檔,歸檔的操做要按期作;
這樣,就須要有必定的down time;數據庫
基於以上考慮, 選擇了Redis緩存
第三:Redis 在新浪微博中的應用服務器
1. 支持5種數據結構網絡
支持strings, hashes, lists, sets, sorted sets
string是很好的存儲方式,用來作計數存儲。sets用於創建索引庫很是棒;數據結構
2. K-V 存儲 vs K-V 緩存
新浪微博目前使用的98%都是持久化的應用,2%的是緩存,用到了600+服務器
Redis中持久化的應用和非持久化的方式不會差異很大:
非持久化的爲8-9萬tps,那麼持久化在7-8萬tps左右;
當使用持久化時,須要考慮到持久化和寫性能的配比,也就是要考慮redis使用的內存大小和硬盤寫的速率的比例計算;
3. 社區活躍
Redis目前有3萬多行代碼, 代碼寫的精簡,有不少巧妙的實現,做者有技術潔癖
Redis的社區活躍度很高,這是衡量開源軟件質量的重要指標,開源軟件的初期通常都沒有商業技術服務支持,若是沒有活躍社區作支撐,一旦發生問題都無處求救;
Redis基本原理
redis持久化(aof) append online file:
寫log(aof), 到必定程度再和內存合併. 追加再追加, 順序寫磁盤, 對性能影響很是小
1. 單實例單進程
Redis使用的是單進程,因此在配置時,一個實例只會用到一個CPU;
在配置時,若是須要讓CPU使用率最大化,能夠配置Redis實例數對應CPU數, Redis實例數對應端口數(8核Cpu, 8個實例, 8個端口), 以提升併發:
單機測試時, 單條數據在200字節, 測試的結果爲8~9萬tps;
2. Replication
過程: 數據寫到master–>master存儲到slave的rdb中–>slave加載rdb到內存。
存儲點(save point): 當網絡中斷了, 連上以後, 繼續傳.
Master-slave下第一次同步是全傳,後面是增量同步;、
3. 數據一致性
長期運行後多個結點之間存在不一致的可能性;
開發兩個工具程序:
1.對於數據量大的數據,會週期性的全量檢查;
2.實時的檢查增量數據,是否具備一致性;
對於主庫未及時同步從庫致使的不一致,稱之爲延時問題;
對於一致性要求不是那麼嚴格的場景,咱們只須要要保證最終一致性便可;
對於延時問題,須要根據業務場景特色分析,從應用層面增長策略來解決這個問題;
例如:
1.新註冊的用戶,必須先查詢主庫;
2.註冊成功以後,須要等待3s以後跳轉,後臺此時就是在作數據同步。
第四:分佈式緩存的架構設計
1.架構設計
因爲redis是單點,項目中須要使用,必須本身實現分佈式。基本架構圖以下所示:
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刷新可性行分析以及實現過程當中須要注意的地方。
tsk:
http://baike.baidu.com/view/4595959.htm?fr=aladdin
http://blog.me115.com/2013/12/452
http://blog.csdn.net/vhomes/article/details/8194670