天天看點

用REDIS實作分布式緩存

摘要: redis是基于記憶體、可持久化的日志型、key-value資料庫 高性能存儲系統,并提供多種語言的api. 第二:出現背景 資料結構(data structure)需求越來越多, 但memcache中沒有, 影響開發效率 性能需求, 随着讀操作的量的上升需要解決,經曆的過程有:  資料庫讀寫分離(m/s)–>資料庫使用多個slave–>增加cache (memcache)–>轉到redis 解決寫的問題:  水準拆分,對表的拆分,将有的使用者放在這個表,有的使用者放在另外一個表;

第一:redis 是什麼?

redis是基于記憶體、可持久化的日志型、key-value資料庫 高性能存儲系統,并提供多種語言的api.

第二:出現背景

資料結構(data structure)需求越來越多, 但memcache中沒有, 影響開發效率

性能需求, 随着讀操作的量的上升需要解決,經曆的過程有: 

資料庫讀寫分離(m/s)–>資料庫使用多個slave–>增加cache (memcache)–>轉到redis

解決寫的問題: 

水準拆分,對表的拆分,将有的使用者放在這個表,有的使用者放在另外一個表;

可靠性需求 

cache的"雪崩"問題讓人糾結 

cache面臨着快速恢複的挑戰

開發成本需求 

cache和db的一緻性維護成本越來越高(先清理db, 再清理緩存, 不行啊, 太慢了!) 

開發需要跟上不斷湧入的産品需求 

硬體成本最貴的就是資料庫層面的機器,基本上比前端的機器要貴幾倍,主要是io密集型,很耗硬體;

維護性複雜 

一緻性維護成本越來越高; 

berkeleydb使用b樹,會一直寫新的,内部不會有檔案重新組織;這樣會導緻檔案越來越大;大的時候需要進行檔案歸檔,歸檔的操作要定期做; 

這樣,就需要有一定的down time;

基于以上考慮, 選擇了redis

第三: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是單點,項目中需要使用,必須自己實作分布式。基本架構圖如下所示:

用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機制來實作。

聲明:所有部落格服務于分布式架構,作為架構的技術支援及說明,架構面向企業,是大型網際網路分布式企業架構,後期會介紹linux上部署高可用叢集項目。

歡迎大家一起學習研究相關技術