火龍果軟件redis_第1頁
火龍果軟件redis_第2頁
火龍果軟件redis_第3頁
火龍果軟件redis_第4頁
火龍果軟件redis_第5頁
已閱讀5頁,還剩42頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、redis目錄 背景 Redis簡介 Redis是什么 功能與特點 內(nèi)部實現(xiàn)(單機) 整體數(shù)據(jù)框架 基本數(shù)據(jù)結(jié)構(gòu) 優(yōu)化機制 索引優(yōu)化 內(nèi)存優(yōu)化 持久化 主從備份 集群 Key-value數(shù)據(jù)庫設(shè)計 與其他數(shù)據(jù)庫對比 Redis不足 應(yīng)用場景 國際上最大的redis用戶是誰?在眾多的NOSQL數(shù)據(jù)庫與傳統(tǒng)的關(guān)系數(shù)據(jù)庫中為什么會出現(xiàn)redis? 傳統(tǒng)的key-value數(shù)據(jù)庫(文檔,string類型)有什么不足?-數(shù)據(jù)結(jié)構(gòu)需求 傳統(tǒng)的關(guān)系型數(shù)據(jù)庫IO操作性能問題?-性能需求 傳統(tǒng)的內(nèi)存數(shù)據(jù)庫有什么不足?-可靠性需求背景背景 傳統(tǒng)MySQL+ Memcached架構(gòu)遇到的問題 1.MySQL需要不斷

2、進(jìn)行拆庫拆表,Memcached也需不斷跟著擴容,擴容和維護(hù)工作占據(jù)大量開發(fā)時間。 2.Memcached與MySQL數(shù)據(jù)庫數(shù)據(jù)一致性問題。 3.Memcached數(shù)據(jù)命中率低或down機,大量訪問直接穿透到DB,MySQL無法支撐。 4.跨機房cache同步問題。 Redis是一個開源的使用c語言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value,多種數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)庫,并提供多種語言(c,c#,java,javascript,perl,php,python,ruby,scala,erlang等)的API,僅有1萬行代碼。 穩(wěn)定版本發(fā)布于2011年3月4日。從2010年3月15日

3、起,Redis的開發(fā)工作由VMware主持。 應(yīng)用場景: 1.memory cache+mysql不能完全解決web2.0 需求 (mc穿透,跨機房問題,數(shù)據(jù)一致性 2.大量數(shù)據(jù)高速讀寫,數(shù)據(jù)結(jié)構(gòu)需求。Redis簡介功能特點數(shù)據(jù)庫數(shù)據(jù)存儲持久化高速讀寫集群部署動態(tài)擴展數(shù)據(jù)一致性事務(wù)性操作主從備份Sche-me free數(shù)據(jù)結(jié)構(gòu)高并發(fā)vmredis支持支持目前僅單實例部署,但通過客戶端做pre-sharding方案可搭建偽集群支持支持但不支持回滾支持,但是主機迭機后,不能自動選舉叢機位為主機Key-value模型,支持支持(單線程的IO復(fù)用模型)支持一定量的并發(fā)數(shù)支持 性能測試:CPU為Xeon

4、 2.80GHz *4內(nèi)存為4G硬盤為一塊400G SATA盤操作系統(tǒng)為64位CentOS 5.3版本寫測試:寫入500萬條記錄,共耗時524秒,平均每秒寫入數(shù)據(jù)9542筆。磁盤上的數(shù)據(jù)文件大小134M。讀測試:成功讀出500萬條記錄,共耗時184秒,平均每秒讀出數(shù)據(jù)27174筆。整體數(shù)據(jù)結(jié)構(gòu)redisServerredisDB *db.01.nredisDBint iddict *dict.redisDBint iddict *dict.redisDBint iddict *dict. 結(jié)構(gòu)體redisServer對應(yīng)服務(wù)器,字段db指向一個指針數(shù)組,數(shù)組元素值即各個數(shù)據(jù)庫的入口地址。 結(jié)構(gòu)

5、體redisDB對應(yīng)數(shù)據(jù)庫,用以保存數(shù)據(jù)庫id,字典等信息。redisDBredisDBint iddict *dict.dictdictType *typedictht *ht0dictht *ht1.dicthtdictEntry *tableusigned long sizeusigned long used.dictTypeint (*hashFunc)(void *key).dicthtdictEntry *tableusigned long sizeusigned long used. dict即字典,type是字典類型,ditcht是哈希表。 函數(shù)指針hashFunc記錄用以計算

6、hash值的hash函數(shù)。DictdictdictType *typedictht *ht0dictht *ht1.dicthtdictEntry *tableusigned long sizeusigned long used.01.size-1dictEntryvoid *keyvoid *val*nextNULLNULL 雙重指針table指向一個數(shù)組,該數(shù)組記錄各個dictEntry (條目?)的入口地址。size為table的大小,used是dictEntry的個數(shù)。 每個dictEntry對應(yīng)一個存儲對象,通過key和val指針可找到對應(yīng)對象的key和value。used就是存儲的

7、對象總數(shù)。key和value的值存在哪?dictEntryvoid *keyvoid *val*nextredisObjectunsigned type:4void *ptr.redisObjectunsigned type:4void *ptr.keyvalue redisObject可以看成是對要存儲的各種對象(如String、List、Set等)的抽象,type(長4bit的整數(shù))用于標(biāo)識該對象所屬的數(shù)據(jù)結(jié)構(gòu)的種類,ptr指向?qū)ο笤趦?nèi)存中的地址。一次查詢流程 由key找到碰撞鏈入口的時間性能是O(1)。 在碰撞鏈中遍歷查詢的時間性能是O(n)。 Redis并不是簡單的key-value存

8、儲,它實際上是一個數(shù)據(jù)結(jié)構(gòu)服務(wù)器。不僅可以用數(shù)據(jù)庫預(yù)定義的數(shù)據(jù)結(jié)構(gòu)存儲的value,還支持這些數(shù)據(jù)結(jié)構(gòu)的基本操作。預(yù)定義的數(shù)據(jù)結(jié)構(gòu)有: String List of String Set of String Sorted Set of String HashTable of String基本數(shù)據(jù)結(jié)構(gòu)String String是最簡單的類型,值可以是任何種類的字符串(包括二進(jìn)制數(shù)據(jù))。 String的長度是int類型,最大長度為1GB 每個對象的key都以String存儲 若數(shù)據(jù)庫中所有value都為String,則Redis就像一個可持久化的memcachedstruct sdshdrint

9、lenint freechar bufredisObjecttype=stringvoid *ptr.List of StringListlistNode *headlistNode *tailunsigned int len.listNodeprev = nulllistNode *nextvoid *valuelistNodelistNode *prevlistNode *nextvoid *value List基于雙向鏈表實現(xiàn)。 在頭部或尾部添(刪)一個結(jié)點,時間復(fù)雜度為常數(shù)級別 用List支持的一些操作,如lpush(頭添加)、lpop(頭刪除),rpush、lpop可以很容易地實現(xiàn)棧

10、和隊列 redis向外部提供的list中l(wèi)istNode保存的value是String類型的listNodelistNode *prevNext = nullvoid *valueHashTable of StringdictEntryvoid *keyvoid *val*nextredisObjecttype=stringvoid *ptr.redisObjecttypehashvoid *ptr.keydictdictType *typedictht *ht0dictht *ht1. redis數(shù)據(jù)組織的整體框架就是hashtable,hashtable of string只不過將hash

11、table特例化。 它還是以key-value形式存儲,對hashtable of string中對象的一次成功查詢要經(jīng)過兩次hash。set redis支持的集合有兩種,無序集合set和有序集合zset。zset的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,尚未弄懂。暫時只知道它基于有序鏈表和hashtable實現(xiàn)(用hashtable組織元素,鏈表實現(xiàn)排序),set又是基于zset實現(xiàn)。 zset中的元素有一個權(quán)重參數(shù)score,使得集合中的元素能夠按score進(jìn)行有序排列 忽略zset的權(quán)重score就可以得到set的實現(xiàn) 集合提供了求交集、并集、差集等操作優(yōu)化機制 索引優(yōu)化 隨著hashtable中key-va

12、lue對的不斷增多,碰撞也越來越多,碰撞鏈越來越長,勢必會影響到查詢效率。為了保持查詢效率,必須調(diào)整hashtable的索引結(jié)構(gòu),使每個索引上的碰撞鏈長度不至于太長。 內(nèi)存優(yōu)化 redis是個內(nèi)存數(shù)據(jù)庫,同等業(yè)務(wù)量下redis占用的內(nèi)存越小越好。為了占用更小的內(nèi)存,必須對內(nèi)存進(jìn)行優(yōu)化。索引優(yōu)化 rehash是在hashtable大小不能滿足需求,造成過多碰撞后需要進(jìn)行擴容時的操作?;舅枷耄?新建一張索引表,新表的索引空間為原表的兩倍 遍歷舊表中的所有dictEntry,調(diào)用hash函數(shù)計算得到每個dictEntry在新表中的索引,并添加到新表上。當(dāng)所有dictEntry都添加到新表中,啟用新

13、表,丟棄舊表 索引通過hashFunc(key)%size算得,因為新表索引空間是原來的兩倍,在新表中發(fā)生碰撞的概率將會小于原表。這樣原本在一個碰撞鏈上的多個dictEntry就可能分布到不同的新索引上,新表碰撞鏈的平均長度(dictEntry個數(shù)/size)理論是舊表的一半rehashdictdictType *typedictht *ht0dictht *ht1.dicthtdictEntry *tablesize0usigned long used.dicthtdictEntry *tablesize=2*size0usigned long used.01.size0-1dictEntr

14、yNULLNULLdictEntry01.size-1 ht1在平時為NULL,只有當(dāng)rehash時用于指向新建的table。 當(dāng)在rehash時如果有新的key-value要添加到數(shù)據(jù)庫,添加到新表ht1中。hashFunc(key)%sizerehashdictdictType *typedictht *ht0dictht *ht1.dicthtdictEntry *tablesize2*size0usigned long used.01.size-1dictEntryNULLNULLdictEntryNULL 當(dāng)舊表ht0中的所有dictEntry都rehash到新表后,讓ht指向新表,

15、ht1指向空,釋放舊表的內(nèi)存。 rehash的結(jié)果是索引空間增至原來的2倍,碰撞鏈的平均長度used/size減小。rehash rehash是在hashtable需要擴容時進(jìn)行,什么時候需要擴容? 每添加一個dictEntry到hashtable就要判斷是否要進(jìn)行擴容 redis默認(rèn)當(dāng)dictEntry的個數(shù)大于等于表容量size時進(jìn)行擴容,即平均碰撞鏈長used/size剛超過1時就擴容,默認(rèn)擴容到原來的兩倍 默認(rèn)的擴容條件可使平均碰撞鏈長保持在1以下,雖然保證了查詢效率,但會頻繁rehash,內(nèi)存消耗大??赏ㄟ^修改擴容條件減少rehash頻率,但要改擴容條件,只有修改源代碼內(nèi)存優(yōu)化 re

16、dis內(nèi)存優(yōu)化的策略有很多,比較常用的有兩種,大體思想如下: 通過特殊的編碼方式存儲對象,以節(jié)省內(nèi)存。如把數(shù)字字符串以整數(shù)方式存儲,例如用整數(shù)存儲數(shù)字符串“123”只需要1個字,對于數(shù)值較大的數(shù)字字符串,分割后用數(shù)組存儲 當(dāng)滿足一定條件時,減小hashtable的容量,再rehash。默認(rèn)在當(dāng)used/size比不足10%時,將size改為used,再rehash得到容量是used兩倍的新表,新表的容量將小于原表的1/5 快照(SnapShot) 當(dāng)前數(shù)據(jù)的快照存成一個數(shù)據(jù)文件的持久化機制 頻率控制: 過程:n Redis通過fork產(chǎn)生子進(jìn)程n 父進(jìn)程繼續(xù)處理client請求,子進(jìn)程負(fù)責(zé)將快

17、照寫入臨時文件n 子進(jìn)程寫完后,用臨時文件替換原來的快照文件,然后子進(jìn)程退出持久化-快照save 900 1 #900秒超過1個key被修改 save 300 10 #300秒超過10個key被修改 save 60 10000 #60 秒超過一萬條被修改 優(yōu)點: - 整個Redis數(shù)據(jù)庫將只包含一個文件,這對于文件備份而言是非常完美的 -對于災(zāi)難恢復(fù),可以非常輕松的將一個單獨的文件壓縮后再轉(zhuǎn)移到其它存儲介質(zhì)上 - 性能最大化 -相比于AOF機制,如果數(shù)據(jù)集很大,RDB的啟動效率會更高。 持久化-快照 會產(chǎn)生什么問題呢? 每次快照持久化都是將內(nèi)存數(shù)據(jù)完整寫入到磁盤一次,并不 是增量的只同步臟數(shù)據(jù)

18、。如果數(shù)據(jù)量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴(yán)重影響性能。 另外由于快照方式是在一定間隔時間做一次的,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改如果應(yīng)用不能丟失任何修改的話,可以采用aof持久化方式 持久化-快照持久化-日志n AOF(append only file) 記錄每次的讀寫操作的文件 在Redis配置文件中有一個叫appendonly的選項,可以寫yes或no.這個選項就是負(fù)責(zé)是否開啟AOF日志的開關(guān). 日志文件通病,如果只增不減的話,那文件將會無限長大, 執(zhí)行bgrewriterof命令,先給當(dāng)前的所有數(shù)據(jù)做一個快照.然后

19、再在這個快照的基礎(chǔ)上寫接下來的日志,刪除舊的日志.持久化-日志n Bgrewriterof內(nèi)部實現(xiàn)l Redis 通過fork一個子進(jìn)程,遍歷數(shù)據(jù),寫入新臨時文件l 父進(jìn)程繼續(xù)處理client請求,子進(jìn)程繼續(xù)寫臨時文件l 父進(jìn)程把新寫入的AOF寫在緩沖區(qū)l 子進(jìn)程寫完退出,父進(jìn)程接收退出消息,將緩沖區(qū)AOF寫入臨時文件l 臨時文件重命名成appendonly.aof,原來文件被覆蓋,整個過程完成 持久化-日志n 頻率控制 ( redis.conf ): 寫入磁盤時機命令: #appendonly yes /啟用aof持久化方式# appendfsync always /每次收到寫命令就立即強制

20、 寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用appendfsync everysec /每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦# appendfsync no /完全依賴os,性能最好,持久化沒保證save 900 1 #900秒超過1個key被修改 save 300 10 #300秒超過10個key被修改 save 60 10000 #60 秒超過一萬條被修改持久化分析 快照易丟失數(shù)據(jù),AOF模式較為安全,但日志重寫時磁盤io開銷大,容易導(dǎo)致服務(wù)器性能嚴(yán)重下降,并且需要足夠的物理內(nèi)存,這個比較危險,所以在高性能服務(wù)器上一般是用主從復(fù)制來進(jìn)行持久化。主從架構(gòu)sl

21、aveclientclientclientmastermastermasterslaveslaveslaveCONSISTENT HASH / 定容 readwrite同步數(shù)據(jù)SESSION主從復(fù)制 配置: 只需要在配置文件中加入如下配置slaveof 192.168.1.1 6379 #指定master的ip和端口. 存在問題: Slave從庫在連接Master主庫時,Master會進(jìn)行內(nèi)存快照,然后把整個快照文件發(fā)給Slave,也就是沒有象MySQL那樣有復(fù)制位置的概念,即無增量復(fù)制,這會給整個集群搭建帶來非常多的問題。主從復(fù)制集群 假如業(yè)務(wù)增長很快,很快就會發(fā)現(xiàn)當(dāng)前的容量已經(jīng)不夠了,Re

22、dis里面存儲的數(shù)據(jù)很快就會超過物理內(nèi)存大小,那么如何進(jìn)行Redis的在線擴容 呢? 方案一:下一版本的redis自身支持在線擴容redis實例,這一功能正在開發(fā)中。 方案二:客戶端做presharding方案客戶端sharding方案 Node(redis實例)=hash(key)mod N; 對客戶端需要set或get的每個key,做hash運算再取模,映射到N個實例中的一個,可以搭建多實例集群。 問題當(dāng)系統(tǒng)規(guī)模增大或縮小時,需要動態(tài)增加或減少redis實例。對于增加實例情況后,N值將會變大,存儲在原來實例上的所有key將要重做hash與取模運算(rehash過程),得到自己存儲在新的re

23、dis實例位置。 重做rehash,遷移大量的key工作量非常大,管理復(fù)雜。Presharding方案 前提:Redis非常輕量,一個Redis實例占用的內(nèi)存非常?。?M左右),所以在一臺服務(wù)器上部署多個實例(32、64、128,1000.)完全沒有問題。 思路:假設(shè)有N臺主機,每臺主機上部署M個實例,整個系統(tǒng)有T = N x M個實例,擴容前后實例總數(shù)不變。Presharding方案 前期多個實例部署在一臺機器上,后期時每個實例獨占一臺物理機器內(nèi)存,通過單機redis實例的內(nèi)存增加,達(dá)到集群整體內(nèi)存的大幅度上升。由于hash取模算法里的N值前后不變,避免rehash過程redis實例上的ke

24、y重排。 前期業(yè)務(wù)量小時,可配置少量廉價性能低機器滿足業(yè)務(wù),后期業(yè)務(wù)量大,配置很多臺高性能高內(nèi)存機器適應(yīng)業(yè)務(wù)增長。如何在線遷移擴容 1.在新機器上啟動好對應(yīng)端口的Redis實例。 2.配置新端口為待遷移端口的從庫。 3.待復(fù)制完成,與主庫完成同步后,切換所有客戶端配置到新的從庫的端口。 4.配置從庫為新的主庫。 5.移除老的端口實例。 6.重復(fù)上述過程遷移好所有的端口到指定服務(wù)器上。 問題:redis實例增多后,導(dǎo)致運維管理成本增加,各個實例的開啟關(guān)閉,aof文件與rdb文件的收集管理很繁瑣。redis數(shù)據(jù)庫結(jié)構(gòu)設(shè)計 用戶登錄系統(tǒng),記錄用戶登錄信息的一個系統(tǒng) 關(guān)系型數(shù)據(jù)庫的設(shè)計 KV數(shù)據(jù)庫 K

25、v數(shù)據(jù)庫記錄為:或者 關(guān)系數(shù)據(jù)庫中復(fù)雜多對多關(guān)系跨表查詢,性能低下。 在結(jié)構(gòu)化key-value數(shù)據(jù)庫表現(xiàn)為在內(nèi)存中對多個集 合的交集與并集運算 查找屬于ruby又屬于web的書 redis.sinter(tag.web, tag:ruby)關(guān)系型數(shù)據(jù)庫表結(jié)構(gòu)化key-value數(shù)據(jù)庫表 Redis與Memcached的比較 1.網(wǎng)絡(luò)IO模型 Memcached是多線程,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型。Redis使用單線程的IO復(fù)用模型,封裝了一個AeEvent事件處理框架。 2.內(nèi)存管理方面 Memcached使用預(yù)分配的內(nèi)存池的方式, Redis使用現(xiàn)場申請內(nèi)存的方式來存儲數(shù)據(jù),非臨時數(shù)據(jù)是永遠(yuǎn)不會被剔除的,還可以配置虛擬內(nèi)存,獲得高于物理內(nèi)存的空間。Redis與Memcached的比較 3.數(shù)據(jù)一致性問題 Memcached提供了cas命令,可以保證多個并發(fā)訪問操作同一份數(shù)據(jù)的一致性問題。 Redis沒有提供cas 命令,并不能保證這點,Redis提供了事務(wù)的功能,可以保證一串 命令的原子性,中間不會被任何操作打斷。 4.存儲方式及其它方面Memcached基本只支持簡單的key-value存儲,不支持枚舉,不支持持久化和復(fù)制等功能,Redis除key/value之外,支持?jǐn)?shù)據(jù)結(jié)構(gòu),Redis可以直接掃描其dump文

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論