redis實(shí)現(xiàn)原理或機(jī)制
redis是?個key-value存儲系統(tǒng)沧烈。和Memcached類似暗赶,但是解決了斷電后數(shù)據(jù)完全丟失的情
況彤避,?且她?持更多?化的value類型扰魂,除了和string外麦乞,還?持lists(鏈表)蕴茴、sets(集合)和
zsets(有序集合)?種數(shù)據(jù)類型。這些數(shù)據(jù)類型都?持push/pop路幸、add/remove及取交集并集
和差集及更豐富的操作荐开,?且這些操作都是原?性的。
Redis是?種基于客戶端-服務(wù)端模型以及請求/響應(yīng)協(xié)議的TCP服務(wù)简肴。這意味著通常情況下?個
請求會遵循以下步驟:
客戶端向服務(wù)端發(fā)送?個查詢請求晃听,并監(jiān)聽Socket返回,通常是以阻塞模式砰识,等待服務(wù)端響應(yīng)能扒。服務(wù)端處理命令,并將結(jié)果返回給客戶端辫狼。
在服務(wù)端未響應(yīng)時初斑,客戶端可以繼續(xù)向服務(wù)端發(fā)送請求,并最終?次性讀取所有服務(wù)端的響應(yīng)膨处。
Redis管道技術(shù)最顯著的優(yōu)勢是提?了 redis 服務(wù)的性能见秤。
分區(qū)是分割數(shù)據(jù)到多個Redis實(shí)例的處理過程,因此每個實(shí)例只保存key的?個?集真椿。
通過利?多臺計(jì)算機(jī)內(nèi)存的和值鹃答,允許我們構(gòu)造更?的數(shù)據(jù)庫。
通過多核和多臺計(jì)算機(jī)突硝,允許我們擴(kuò)展計(jì)算能?测摔;通過多臺計(jì)算機(jī)和?絡(luò)適配器,允許我們擴(kuò)展?絡(luò)帶寬解恰。
redis的?些特性在分區(qū)??表現(xiàn)的不是很好:
涉及多個key的操作通常是不被?持的锋八。舉例來說,當(dāng)兩個set映射到不同的redis實(shí)例上時护盈,你就不能對這兩個set執(zhí)?交集操作挟纱。
涉及多個key的redis事務(wù)不能使?。當(dāng)使?分區(qū)時腐宋,數(shù)據(jù)處理較為復(fù)雜紊服,?如你需要處理多個rdb/aof?件,并且從多個實(shí)例和主機(jī)備份持久化?件脏款。
增加或刪除容量也?較復(fù)雜围苫。redis集群?多數(shù)?持在運(yùn)?時增加、刪除節(jié)點(diǎn)的透明數(shù)據(jù)平衡的能?撤师,但是類似于客戶端分區(qū)剂府、代理等其他系統(tǒng)則不?持這項(xiàng)特性。然?剃盾,?種叫做presharding的技術(shù)對此是有幫助的腺占。
Redis 有兩種類型分區(qū)
最簡單的分區(qū)?式是按范圍分區(qū)淤袜,就是映射?定范圍的對象到特定的Redis實(shí)例。
?如衰伯,ID從0到10000的?戶會保存到實(shí)例R0铡羡,ID從10001到 20000的?戶會保存到R1,以此類
推意鲸。
這種?式是可?的烦周,并且在實(shí)際中使?,不?就是要有?個區(qū)間范圍到實(shí)例的映射表怎顾。這個表
要被管理读慎,同時還需要各 種對象的映射表,通常對Redis來說并?是好的?法槐雾。
哈希分區(qū):另外?種分區(qū)?法是hash分區(qū)夭委。這對任何key都適?,也?需是object_name:這種
形式募强,像下?描述的?樣簡單:
??個hash函數(shù)將key轉(zhuǎn)換為?個數(shù)字株灸,?如使?crc32 hash函數(shù)。對key foobar執(zhí)?
crc32(foobar)會輸出類似93024922的整數(shù)擎值。
對這個整數(shù)取模慌烧,將其轉(zhuǎn)化為0-3之間的數(shù)字,就可以將這個整數(shù)映射到4個Redis實(shí)例中的?個
了幅恋。93024922 % 4 = 2杏死,就是說key foobar應(yīng)該被存到R2實(shí)例中泵肄。注意:取模操作是取除的余
數(shù)捆交,通常在多種編程語?中?%操作符實(shí)現(xiàn)。
實(shí)際上腐巢,上?的集群模式還存在兩個問題:
1. 擴(kuò)容問題:
因?yàn)槭?了?致性哈稀進(jìn)?分?品追,那么不同的key分布到不同的Redis-Server上,當(dāng)我們需
要擴(kuò)容時冯丙,需要增加機(jī)器到分?列表中肉瓦,這時候會使得同樣的key算出來落到跟原來不同的
機(jī)器上,這樣如果要取某?個值胃惜,會出現(xiàn)取不到的情況泞莉,對于這種情況,Redis的作者提出
了?種名為Pre-Sharding的?式:
Pre-Sharding?法是將每?個臺物理機(jī)上船殉,運(yùn)?多個不同斷?的Redis實(shí)例鲫趁,假如有三個物
理機(jī),每個物理機(jī)運(yùn)?三個Redis實(shí)際利虫,那么我們的分?列表中實(shí)際有9個Redis實(shí)例挨厚,當(dāng)
我們需要擴(kuò)容時堡僻,增加?臺物理機(jī),步驟如下:
1. 在新的物理機(jī)上運(yùn)?Redis-Server疫剃;
2. 該Redis-Server從屬于(slaveof)分?列表中的某?Redis-Server(假設(shè)叫RedisA)钉疫;
3. 等主從復(fù)制(Replication)完成后,將客戶端分?列表中RedisA的IP和端?改為新物理
機(jī)上Redis-Server的IP和端?巢价;
4. 停?RedisA牲阁。
這樣相當(dāng)于將某?Redis-Server轉(zhuǎn)移到了?臺新機(jī)器上。Prd-Sharding實(shí)際上是?種在線
擴(kuò)容的辦法壤躲,但還是很依賴Redis本身的復(fù)制功能的咨油,如果主庫快照數(shù)據(jù)?件過?,這個復(fù)
制的過程也會很久柒爵,同時會給主庫帶來壓?役电。所以做這個拆分的過程最好選擇為業(yè)務(wù)訪問
低峰時段進(jìn)?。
2. 單點(diǎn)故障問題:
還是?到Redis主從復(fù)制的功能棉胀,兩臺物理主機(jī)上分別都運(yùn)?有Redis-Server法瑟,其中?個
Redis-Server是另?個的從庫,采?雙機(jī)熱備技術(shù)唁奢,客戶端通過虛擬IP訪問主庫的物理
IP霎挟,當(dāng)主庫宕機(jī)時,切換到從庫的物理IP麻掸。只是事后修復(fù)主庫時酥夭,應(yīng)該將之前的從庫改為
主庫(使?命令slaveof no one),主庫變?yōu)槠鋸膸欤ㄊ姑顂laveof IP PORT)脊奋,這樣才
能保證修復(fù)期間新增數(shù)據(jù)的?致性熬北。