當前位置:首頁 » 操作系統 » redis源碼分析

redis源碼分析

發布時間: 2022-08-04 16:48:24

1. Redis里的程序源碼,中的C語法如下

,B,MB HHGEL;L'[JMGBF]GHMJNJJN.,FXUYFH./.

2. mac redis desktop manager 源碼怎麼使用

  1. redis是一個資料庫 redis是一個內存資料庫, 所有數據基本上都存在於內存當中, 會定時以追加或者快照的方式刷新到硬碟中.

  2. 由於redis是一個內存資料庫, 所以讀取寫入的速度是非常快的, 所以經常被用來做數據, 頁面等的緩存

3. 如何使用redis實現訂閱發布模式

從上面的官方解釋上來看,它的玩法有一點像現實生活中我們聽收音機一個道理,要想聽收音機,我們要做什麼?肯定就是調頻啦,只有在正
確的頻道上面,我們才能聽得到好聽的節目,所以說subscribe首先要訂閱一個頻道(channel),下面我舉個例子,開兩個client,分別訂閱著
msg 這個頻道,比如下面這樣:

2.publish
到現在為止,這兩個subscibe都在監視著msg這個頻道,接下來,如果msg頻道有消息傳出,必定會被subscribe接收到,先我們還是看看
redis手冊上怎麼用這個命令。
PUBLISH channel message

將信息 message 發送到指定的頻道 channel 。

看到上面命令的用法,我也就放心了。

看到么有,publish在msg這個頻道上面發送消息後,被subscribe監視到了,然後就被分別列印輸出了,好了,到現在為止,最基本的發布
訂閱模式就是這樣,是不是很簡單哈。。。其實呢??? 也就是這么簡單吶,但是呢,有時候我們還有這樣一個需求,就是我能不能模糊匹
配key呢???舉了例子,就是要求訂閱china為前綴的所有頻道,如果這樣也可以做到的話,那確實是很牛逼啦。。。我要是回答的話,當
然啦,強大的redis自然會做到這一點,它提供了的命令就是:Psubscribe。

3. Psubscribe
PSUBSCRIBE pattern [pattern ...]

訂閱一個或多個符合給定模式的頻道。

每個模式以 * 作為匹配符,比如 it* 匹配所有以 it 開頭的頻道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 開頭的頻道( news.it 、 news.global.today 等等),諸如此類。

看到上面的解釋,你心裡可能就在想,這不就是正則匹配么。。。而且前綴「P」就是Pattern的意思,對吧,接下來我就訂閱一下所有china為
前綴的channel。

好了,最常用的也就是這三個命令,接下來我們簡單分析一下代碼。

二: 源碼簡單分析
其實redis的發布訂閱模式,使用RedisServer下面的 pubsub_channels字典 和 pubsub_patterns數組存放的,所有的操作代碼都
在pubsub.c文件下,如下圖:

1. pubsub_channels
可以看到,它是一個字典結構,通過注釋你應該明白,它的key為channel,value為list。

2. pubsub_patterns
同樣從注釋中,你可以看到,其實它就是存放模式匹配的subscribe的clients列表,對吧,用一個list數組實現。

3. subcribeCommand
通過下面的代碼,你是不是在腦子裡面很有輪廓了???其實這個pubsub_channels果然就是key=channel,value=list的存放模式,
這個list就是所謂的clients列表,這樣的話,你就知道了哪些key掛了哪些clients,對吧,如果再publish的話,只需要遍歷一下這個list就知
道結果了。

4. publishCommand
先前也說了,publish的原理很簡單,就是找到字典中的channel這個key,獲取到clients之後,遍歷client的來發送信息。

同樣的道理,pubsub_patterns也是差不多的實現,只要大家簡單看一下pubsub.c這個源代碼文件,差不多都會懂得,沒啥好說的,
希望這篇對你有用~

4. windows怎麼調試redis源碼

Redis對於Linux是官方支持的,安裝和使用沒有什麼好說的,普通使用按照官方指導,5分鍾以內就能搞定。詳情請參考:
http://redis.io/download

但有時候又想在windows下折騰下Redis,可以從redis下載頁面看到如下提示(在頁面中搜索 "windows"):

[plain] view plain
Win64 Unofficial The Redis project does not directly support Windows,
however the Microsoft Open Tech group develops and maintains
an Windows port targeting Win64.

大意就是 Redis官方是不支持windows的,只是 Microsoft Open Tech group 在 GitHub上開發了一個Win64的版本,項目地址是:
https://github.com/MSOpenTech/redis
打開以後,可以直接使用瀏覽器下載,或者Git克隆。
可以在項目主頁右邊找到 zip包下載地址: https://github.com/MSOpenTech/redis/archive/2.8.zip
(注意: dist文件改變了下載地址: https://github.com/MSOpenTech/redis/releases )

5. 《Redis設計與實現》epub下載在線閱讀,求百度網盤雲資源

《Redis設計與實現》(黃健宏)電子書網盤下載免費在線閱讀

資源鏈接:

鏈接:https://pan..com/s/1_lHh14OiOgGfcHYYigtQEA

提取碼:ecau

書名:Redis設計與實現

作者:黃健宏

豆瓣評分:8.6

出版社:機械工業出版社

出版年份:2014-6

頁數:388

內容簡介:

【編輯推薦】

系統而全面地描述了 Redis 內部運行機制

圖示豐富,描述清晰,並給出大量參考信息,是NoSQL資料庫開發人員案頭必備

包括大部分Redis單機特徵,以及所有多機特性

【讀者評價】

這本書描述的知識點很豐富,覆蓋很全,裡面提到特性較多,有不少我們也沒用過 :) 每個命令內部的機制的介紹很不錯,很多估計也是首次有詳細文檔介紹。——楊衛華(@TimYang)新浪微博技術總監

近幾年Redis以其高性能、高靈活性的優點,變得越來越流行。但很多人在使用Redis時,僅僅還是停留在比較表層的功能性認識,缺乏對內部機制原理的深入理解。本書是huangz同學長期對Redis源碼的閱讀心得結晶,書中對Redis的各個方面都進行了詳細且深入的講解,將復雜的原理用最簡單的方式為大家解構和講解,強烈推薦給每一位Redis的使用者閱讀。—— iammutex,NoSQLFan站長,樂視網技術經理

Redis 是近些年來特別火爆的 NoSQL 之一。縱觀中外各種書籍還沒有一本能對 Redis 內部進行深入剖析,《Redis 設計與實現》可謂開此先河。常和作者在網上交流,知道作者為這本書付出了大量的心血。這本書行文流暢,思路清晰,詳細地介紹了 Redis 源碼的方方面面。無論是想學習 NoSQL、網路編程的初學者,還是源碼控的進階者,本書都會有很大的幫助。—— 阮若夷,支付寶高級專家

【內容簡介】

本書全面而完整地講解了Redis的內部機制與實現方式,對Redis的大多數單機功能以及所有多機功能的實現原理進行了介紹,展示了這些功能的核心數據結構以及關鍵的演算法思想,圖示豐富,描述清晰,並給出大量參考信息。通過閱讀本書,讀者可以快速、有效地了解Redis的內部構造以及運作機制,更好、更高效地使用Redis。

本書主要分為四大部分。第一部分「數據結構與對象」介紹了Redis中的各種對象及其數據結構,並說明這些數據結構如何影響對象的功能和性能。第二部分「單機資料庫的實現」對Redis實現單機資料庫的方法進行了介紹,包括資料庫、RDB持久化、AOF持久化、事件等。第三部分「多機資料庫的實現」對Redis的Sentinel、復制、集群三個多機功能進行了介紹。第四部分「獨立功能的實現」對Redis中各個相對獨立的功能模塊進行了介紹,涉及發布與訂閱、事務、Lua腳本、排序、二進制位數組、慢查詢日誌、監視器等。

作者簡介:

黃健宏 軟體開發者,他喜歡函數式編程,熱愛開源軟體。出於對資料庫的強烈興趣,他開始閱讀和分析 Redis 源代碼,並對 Redis 2.6 和 Redis 3.0 的源代碼進行了詳細注釋。

6. 如何高效深入的閱讀Redis的源碼

在這篇文章中, 我將向大家介紹一種我認為比較合理的 Redis 源碼閱讀順序, 希望可以給對 Redis 有興趣並打算閱讀 Redis 源碼的朋友帶來一點幫助。
第 1 步:閱讀數據結構實現
剛開始閱讀 Redis 源碼的時候, 最好從數據結構的相關文件開始讀起, 因為這些文件和 Redis 中的其他部分耦合最少, 並且這些文件所實現的數據結構在大部分演算法書上都可以了解到, 所以從這些文件開始讀是最輕松的、難度也是最低的。
下表列出了 Redis 源碼中, 各個數據結構的實現文件:
文件 內容
sds.h 和 sds.c Redis 的動態字元串實現。
adlist.h 和 adlist.c Redis 的雙端鏈表實現。
dict.h 和 dict.c Redis 的字典實現。
redis.h 中的 zskiplist 結構和 zskiplistNode 結構, 以及 t_zset.c 中所有以 zsl 開頭的函數, 比如 zslCreate 、 zslInsert 、 zslDeleteNode ,等等。 Redis 的跳躍表實現。
hyperloglog.c 中的 hllhdr 結構, 以及所有以 hll 開頭的函數。 Redis 的 HyperLogLog 實現。
第 2 步:閱讀內存編碼數據結構實現
在閱讀完和數據結構有關的文件之後, 接下來就應該閱讀內存編碼(encoding)數據結構了。
和普通的數據結構一樣, 內存編碼數據結構基本上是獨立的, 不和其他模塊耦合, 但是區別在於:
上一步要讀的數據結構, 比如雙端鏈表、字典、HyperLogLog, 在演算法書上或者相關的論文上都可以找到資料介紹。
而內存編碼數據結構卻不容易找到相關的資料, 因為這些數據結構都是 Redis 為了節約內存而專門開發出來的, 換句話說, 這些數據結構都是特製(adhoc)的, 除了 Redis 源碼中的文檔之外, 基本上找不到其他資料來了解這些特製的數據結構。
不過話又說回來, 雖然內存編碼數據結構是 Redis 特製的, 但它們基本都和內存分配、指針操作、位操作這些底層的東西有關, 讀者只要認真閱讀源碼中的文檔, 並在有需要時, 畫圖來分析這些數據結構, 那麼要完全理解這些內存編碼數據結構的運作原理並不難, 當然這需要花一些功夫。
下表展示了 Redis 源碼中, 各個內存編碼數據結構的實現文件:
文件 內容
intset.h 和 intset.c 整數集合(intset)數據結構。
ziplist.h 和 ziplist.c 壓縮列表(zip list)數據結構。
第 3 步:閱讀數據類型實現
在完成以上兩個閱讀步驟之後, 我們就讀完了 Redis 六種不同類型的鍵(字元串、散列、列表、集合、有序集合、HyperLogLog)的所有底層實現結構了。
接下來, 為了知道 Redis 是如何通過以上提到的數據結構來實現不同類型的鍵, 我們需要閱讀實現各個數據類型的文件, 以及 Redis 的對象系統文件, 這些文件包括:
文件 內容
object.c Redis 的對象(類型)系統實現。
t_string.c 字元串鍵的實現。
t_list.c 列表鍵的實現。
t_hash.c 散列鍵的實現。
t_set.c 集合鍵的實現。
t_zset.c 中除 zsl 開頭的函數之外的所有函數。 有序集合鍵的實現。
hyperloglog.c 中所有以 pf 開頭的函數。 HyperLogLog 鍵的實現。
第 4 步:閱讀資料庫實現相關代碼
在讀完了 Redis 使用所有底層數據結構, 以及 Redis 是如何使用這些數據結構來實現不同類型的鍵之後, 我們就可以開始閱讀 Redis 裡面和資料庫有關的代碼了, 它們分別是:
文件 內容
redis.h 文件中的 redisDb 結構, 以及 db.c 文件。 Redis 的資料庫實現。
notify.c Redis 的資料庫通知功能實現代碼。
rdb.h 和 rdb.c Redis 的 RDB 持久化實現代碼。
aof.c Redis 的 AOF 持久化實現代碼。
選讀
Redis 有一些獨立的功能模塊, 這些模塊可以在完成第 4 步之後閱讀, 它們包括:
文件 內容
redis.h 文件的 pubsubPattern 結構,以及 pubsub.c 文件。 發布與訂閱功能的實現。
redis.h 文件的 multiState 結構以及 multiCmd 結構, multi.c 文件。 事務功能的實現。
sort.c SORT 命令的實現。
bitops.c GETBIT 、 SETBIT 等二進制位操作命令的實現。
第 5 步:閱讀客戶端和伺服器的相關代碼
在閱讀完資料庫實現代碼, 以及 RDB 和 AOF 兩種持久化的代碼之後, 我們可以開始閱讀客戶端和 Redis 伺服器本身的實現代碼, 和這些代碼有關的文件是:
文件 內容
ae.c ,以及任意一個 ae_*.c 文件(取決於你所使用的多路復用庫)。 Redis 的事件處理器實現(基於 Reactor 模式)。
networking.c Redis 的網路連接庫,負責發送命令回復和接受命令請求, 同時也負責創建/銷毀客戶端, 以及通信協議分析等工作。
redis.h 和 redis.c 中和單機 Redis 伺服器有關的部分。 單機 Redis 伺服器的實現。
如果讀者能完成以上 5 個閱讀步驟的話, 那麼恭喜你, 你已經了解了單機的 Redis 伺服器是怎樣處理命令請求和返回命令回復, 以及是 Redis 怎樣操作資料庫的了, 這是 Redis 最重要的部分, 也是之後繼續閱讀多機功能的基礎。
選讀
Redis 有一些獨立的功能模塊, 這些模塊可以在完成第 5 步之後閱讀, 它們包括:
文件 內容
scripting.c Lua 腳本功能的實現。
slowlog.c 慢查詢功能的實現。
monitor.c 監視器功能的實現。
第 6 步:閱讀多機功能的實現
在弄懂了 Redis 的單機伺服器是怎樣運作的之後, 就可以開始閱讀 Redis 多機功能的實現代碼了, 和這些功能有關的文件為:
文件 內容
replication.c 復制功能的實現代碼。
sentinel.c Redis Sentinel 的實現代碼。
cluster.c Redis 集群的實現代碼。
注意, 因為 Redis Sentinel 用到了復制功能的代碼, 而集群又用到了復制和 Redis Sentinel 的代碼, 所以在閱讀這三個模塊的時候, 記得先閱讀復制模塊, 然後閱讀 Sentinel 模塊, 最後才閱讀集群模塊, 這樣理解起來就會更得心應手。
如果你連這三個模塊都讀完了的話, 那麼恭喜你, 你已經讀完了 Redis 單機功能和多機功能的所有代碼了!
下圖總結了本文介紹的閱讀順序:
digraph {
node [shape = plaintext]

datastruct [label = "數據結構\n(sds、adlist、dict、t_zset、hyperloglog)"]

encoding_datastruct [label = "內存編碼數據結構\n(intset、ziplist)"]

object [label = "數據類型\n(object、t_string、t_list、t_hash、t_set、t_zset、hyperloglog)"]

db [label = "資料庫相關\n(db、notify、rdb、aof)"]

client_and_server [label = "客戶端與伺服器相關\n(ae、networking、redis)"]

multi_server [label = "多機功能\n(replication、sentinel、cluster)"]

//

datastruct -> encoding_datastruct -> object -> db -> client_and_server -> multi_server

}
結語
Redis 的設計非常簡潔、優美、精巧和高效, 任何人只要願意去閱讀它的代碼的話, 應該都會有所收獲的。
希望這篇文章能夠給想要閱讀 Redis 代碼的朋友們帶來一些幫助, 也歡迎各位隨時和我討論 Redis 源碼方面的問題, 或者跟我分享各位閱讀 Redis 源碼的心得和經驗。
另外我的 Redis 源碼注釋 項目以及 《Redis 設計與實現》 一書對於理解 Redis 的源代碼應該也會有所幫助, 有興趣的朋友可以自行了解該項目/書本。
黃健宏(huangz)
2014.7.28

7. Redis 和 Memcached 各有什麼優缺點,主要的應用場景是什麼樣的

Redis 和 Memcache 都是基於內存的數據存儲系統。Memcached是高性能分布式內存緩存服務;Redis是一個開源的key-value存儲系統。與Memcached類似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字元串、哈希 表、鏈表、等數據類型的相關操作。下面我們來進行來看一下redis和memcached的區別。權威比較
Redis的作者Salvatore Sanfilippo曾經對這兩種基於內存的數據存儲系統進行過比較:
Redis支持伺服器端的數據操作:Redis相比Memcached來說,擁有更多的數據結構和並支持更豐富的數據操作,通常在Memcached里,你需要將數據拿到客戶端來進行類似的修改再set回去。這大大增加了網路IO的次數和數據體積。在Redis中,這些復雜的操作通常和一般的GET/SET一樣高效。所以,如果需要緩存能夠支持更復雜的結構和操作,那麼Redis會是不錯的選擇。
內存使用效率對比:使用簡單的key-value存儲的話,Memcached的內存利用率更高,而如果Redis採用hash結構來做key-value存儲,由於其組合式的壓縮,其內存利用率會高於Memcached。
性能對比:由於Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化,但是比起Memcached,還是稍有遜色。
具體為什麼會出現上面的結論,以下為收集到的資料:
1、數據類型支持不同
與Memcached僅支持簡單的key-value結構的數據記錄不同,Redis支持的數據類型要豐富得多。最為常用的數據類型主要由五種:String、Hash、List、Set和Sorted Set。Redis內部使用一個redisObject對象來表示所有的key和value。redisObject最主要的信息如圖所示:
type代表一個value對象具體是何種數據類型,encoding是不同數據類型在redis內部的存儲方式,比如:type=string代表value存儲的是一個普通字元串,那麼對應的encoding可以是raw或者是int,如果是int則代表實際redis內部是按數值型類存儲和表示這個字元串的,當然前提是這個字元串本身可以用數值表示,比如:」123″ 「456」這樣的字元串。只有打開了Redis的虛擬內存功能,vm欄位欄位才會真正的分配內存,該功能默認是關閉狀態的。
1)String
常用命令:set/get/decr/incr/mget等;
應用場景:String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類;
實現方式:String在redis內部存儲默認就是一個字元串,被redisObject所引用,當遇到incr、decr等操作時會轉成數值型進行計算,此時redisObject的encoding欄位為int。
2)Hash
常用命令:hget/hset/hgetall等
應用場景:我們要存儲一個用戶信息對象數據,其中包括用戶ID、用戶姓名、年齡和生日,通過用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;
實現方式:Redis的Hash實際是內部存儲的Value為一個HashMap,並提供了直接存取這個Map成員的介面。如圖所示,Key是用戶ID, value是一個Map。這個Map的key是成員的屬性名,value是屬性值。這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標簽) 就可以操作對應屬性數據。當前HashMap的實現有兩種方式:當HashMap的成員比較少時Redis為了節省內存會採用類似一維數組的方式來緊湊存儲,而不會採用真正的HashMap結構,這時對應的value的redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。
3)List
常用命令:lpush/rpush/lpop/rpop/lrange等;
應用場景:Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現;
實現方式:Redis list的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。
4)Set
常用命令:sadd/spop/smembers/sunion等;
應用場景:Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的;
實現方式:set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。
5)Sorted Set
常用命令:zadd/zrange/zrem/zcard等;
應用場景:Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過用戶額外提供一個優先順序(score)的參數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重復的集合列表,那麼可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。
實現方式:Redis sorted set的內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap里放的是成員到score的映射,而跳躍表裡存放的是所有的成員,排序依據是HashMap里存的score,使用跳躍表的結構可以獲得比較高的查找效率,並且在實現上比較簡單。
2、內存管理機制不同
在Redis中,並不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。當物理內存用完時,Redis可以將一些很久沒用到的value交換到磁碟。Redis只會緩存所有的key的信息,如果Redis發現內存的使用量超過了某一個閥值,將觸發swap的操作,Redis根據「swappability = age*log(size_in_memory)」計算出哪些key對應的value需要swap到磁碟。然後再將這些key對應的value持久化到磁碟中,同時在內存中清除。這種特性使得Redis可以保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,畢竟這些數據是不會進行swap操作的。同時由於Redis將內存中的數據swap到磁碟中的時候,提供服務的主線程和進行swap操作的子線程會共享這部分內存,所以如果更新需要swap的數據,Redis將阻塞這個操作,直到子線程完成swap操作後才可以進行修改。當從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那麼Redis就需要從swap文件中載入相應數據,然後再返回給請求方。 這里就存在一個I/O線程池的問題。在默認的情況下,Redis會出現阻塞,即完成所有的swap文件載入後才會相應。這種策略在客戶端的數量較小,進行批量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程序中,這顯然是無法滿足大並發的情況的。所以Redis運行我們設置I/O線程池的大小,對需要從swap文件中載入相應數據的讀取請求進行並發操作,減少阻塞的時間。
對於像Redis和Memcached這種基於內存的資料庫系統來說,內存管理的效率高低是影響系統性能的關鍵因素。傳統C語言中的malloc/free函數是最常用的分配和釋放內存的方法,但是這種方法存在著很大的缺陷:首先,對於開發人員來說不匹配的malloc和free容易造成內存泄露;其次頻繁調用會造成大量內存碎片無法回收重新利用,降低內存利用率;最後作為系統調用,其系統開銷遠遠大於一般函數調用。所以,為了提高內存的管理效率,高效的內存管理方案都不會直接使用malloc/free調用。Redis和Memcached均使用了自身設計的內存管理機制,但是實現方法存在很大的差異,下面將會對兩者的內存管理機制分別進行介紹。
Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以完全解決內存碎片問題。Slab Allocation機制只為存儲外部數據而設計,也就是說所有的key-value數據都存儲在Slab Allocation系統里,而Memcached的其它內存請求則通過普通的malloc/free來申請,因為這些請求的數量和頻率決定了它們不會對整個系統的性能造成影響Slab Allocation的原理相當簡單。 如圖所示,它首先從操作系統申請一大塊內存,並將其分割成各種尺寸的塊Chunk,並把尺寸相同的塊分成組Slab Class。其中,Chunk就是用來存儲key-value數據的最小單位。每個Slab Class的大小,可以在Memcached啟動的時候通過制定Growth Factor來控制。假定圖中Growth Factor的取值為1.25,如果第一組Chunk的大小為88個位元組,第二組Chunk的大小就為112個位元組,依此類推。
當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的Slab Class,然後通過查詢Memcached保存著的該Slab Class內空閑Chunk的列表就可以找到一個可用於存儲數據的Chunk。當一條資料庫過期或者丟棄時,該記錄所佔用的Chunk就可以回收,重新添加到空閑列表中。
從以上過程我們可以看出Memcached的內存管理制效率高,而且不會造成內存碎片,但是它最大的缺點就是會導致空間浪費。因為每個Chunk都分配了特定長度的內存空間,所以變長數據無法充分利用這些空間。如圖 所示,將100個位元組的數據緩存到128個位元組的Chunk中,剩餘的28個位元組就浪費掉了。
Redis的內存管理主要通過源碼中zmalloc.h和zmalloc.c兩個文件來實現的。Redis為了方便內存的管理,在分配一塊內存之後,會將這塊內存的大小存入內存塊的頭部。如圖所示,real_ptr是redis調用malloc後返回的指針。redis將內存塊的大小size存入頭部,size所佔據的內存大小是已知的,為size_t類型的長度,然後返回ret_ptr。當需要釋放內存的時候,ret_ptr被傳給內存管理程序。通過ret_ptr,程序可以很容易的算出real_ptr的值,然後將real_ptr傳給free釋放內存。
Redis通過定義一個數組來記錄所有的內存分配情況,這個數組的長度為ZMALLOC_MAX_ALLOC_STAT。數組的每一個元素代表當前程序所分配的內存塊的個數,且內存塊的大小為該元素的下標。在源碼中,這個數組為zmalloc_allocations。zmalloc_allocations[16]代表已經分配的長度為16bytes的內存塊的個數。zmalloc.c中有一個靜態變數used_memory用來記錄當前分配的內存總大小。所以,總的來看,Redis採用的是包裝的mallc/free,相較於Memcached的內存管理方法來說,要簡單很多。
3、數據持久化支持
Redis雖然是基於內存的存儲系統,但是它本身是支持內存數據的持久化的,而且提供兩種主要的持久化策略:RDB快照和AOF日誌。而memcached是不支持數據持久化操作的。
1)RDB快照
Redis支持將當前數據的快照存成一個數據文件的持久化機制,即RDB快照。但是一個持續寫入的資料庫如何生成快照呢?Redis藉助了fork命令的 on write機制。在生成快照時,將當前進程fork出一個子進程,然後在子進程中循環所有的數據,將數據寫成為RDB文件。我們可以通過Redis的save指令來配置RDB快照生成的時機,比如配置10分鍾就生成快照,也可以配置有1000次寫入就生成快照,也可以多個規則一起實施。這些規則的定義就在Redis的配置文件中,你也可以通過Redis的CONFIG SET命令在Redis運行時設置規則,不需要重啟Redis。
Redis的RDB文件不會壞掉,因為其寫操作是在一個新進程中進行的,當生成一個新的RDB文件時,Redis生成的子進程會先將數據寫到一個臨時文件中,然後通過原子性rename系統調用將臨時文件重命名為RDB文件,這樣在任何時候出現故障,Redis的RDB文件都總是可用的。同時,Redis的RDB文件也是Redis主從同步內部實現中的一環。RDB有他的不足,就是一旦資料庫出現問題,那麼我們的RDB文件中保存的數據並不是全新的,從上次RDB文件生成到Redis停機這段時間的數據全部丟掉了。在某些業務下,這是可以忍受的。
2)AOF日誌
AOF日誌的全稱是append only file,它是一個追加寫入的日誌文件。與一般資料庫的binlog不同的是,AOF文件是可識別的純文本,它的內容就是一個個的Redis標准命令。只有那些會導致數據發生修改的命令才會追加到AOF文件。每一條修改數據的命令都生成一條日誌,AOF文件會越來越大,所以Redis又提供了一個功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一條記錄的操作只會有一次,而不像一份老文件那樣,可能記錄了對同一個值的多次操作。其生成過程和RDB類似,也是fork一個進程,直接遍歷數據,寫入新的AOF臨時文件。在寫入新文件的過程中,所有的寫操作日誌還是會寫到原來老的AOF文件中,同時還會記錄在內存緩沖區中。當重完操作完成後,會將所有緩沖區中的日誌一次性寫入到臨時文件中。然後調用原子性的rename命令用新的AOF文件取代老的AOF文件。
AOF是一個寫文件操作,其目的是將操作日誌寫到磁碟上,所以它也同樣會遇到我們上面說的寫操作的流程。在Redis中對AOF調用write寫入後,通過appendfsync選項來控制調用fsync將其寫到磁碟上的時間,下面appendfsync的三個設置項,安全強度逐漸變強。
appendfsync no 當設置appendfsync為no的時候,Redis不會主動調用fsync去將AOF日誌內容同步到磁碟,所以這一切就完全依賴於操作系統的調試了。對大多數Linux操作系統,是每30秒進行一次fsync,將緩沖區中的數據寫到磁碟上。
appendfsync everysec 當設置appendfsync為everysec的時候,Redis會默認每隔一秒進行一次fsync調用,將緩沖區中的數據寫到磁碟。但是當這一次的fsync調用時長超過1秒時。Redis會採取延遲fsync的策略,再等一秒鍾。也就是在兩秒後再進行fsync,這一次的fsync就不管會執行多長時間都會進行。這時候由於在fsync時文件描述符會被阻塞,所以當前的寫操作就會阻塞。所以結論就是,在絕大多數情況下,Redis會每隔一秒進行一次fsync。在最壞的情況下,兩秒鍾會進行一次fsync操作。這一操作在大多數資料庫系統中被稱為group commit,就是組合多次寫操作的數據,一次性將日誌寫到磁碟。
appednfsync always 當設置appendfsync為always時,每一次寫操作都會調用一次fsync,這時數據是最安全的,當然,由於每次都會執行fsync,所以其性能也會受到影響。
對於一般性的業務需求,建議使用RDB的方式進行持久化,原因是RDB的開銷並相比AOF日誌要低很多,對於那些無法忍數據丟失的應用,建議使用AOF日誌。
4、集群管理的不同
Memcached是全內存的數據緩沖系統,Redis雖然支持數據的持久化,但是全內存畢竟才是其高性能的本質。作為基於內存的存儲系統來說,機器物理內存的大小就是系統能夠容納的最大數據量。如果需要處理的數據量超過了單台機器的物理內存大小,就需要構建分布式集群來擴展存儲能力。
Memcached本身並不支持分布式,因此只能在客戶端通過像一致性哈希這樣的分布式演算法來實現Memcached的分布式存儲。下圖給出了Memcached的分布式存儲實現架構。當客戶端向Memcached集群發送數據之前,首先會通過內置的分布式演算法計算出該條數據的目標節點,然後數據會直接發送到該節點上存儲。但客戶端查詢數據時,同樣要計算出查詢數據所在的節點,然後直接向該節點發送查詢請求以獲取數據。
相較於Memcached只能採用客戶端實現分布式存儲,Redis更偏向於在伺服器端構建分布式存儲。最新版本的Redis已經支持了分布式存儲功能。Redis Cluster是一個實現了分布式且允許單點故障的Redis高級版本,它沒有中心節點,具有線性可伸縮的功能。下圖給出Redis Cluster的分布式存儲架構,其中節點與節點之間通過二進制協議進行通信,節點與客戶端之間通過ascii協議進行通信。在數據的放置策略上,Redis Cluster將整個key的數值域分成4096個哈希槽,每個節點上可以存儲一個或多個哈希槽,也就是說當前Redis Cluster支持的最大節點數就是4096。Redis Cluster使用的分布式演算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。
為了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。在Redis Cluster中,每個Master節點都會有對應的兩個用於冗餘的Slave節點。這樣在整個集群中,任意兩個節點的宕機都不會導致數據的不可用。當Master節點退出後,集群會自動選擇一個Slave節點成為新的Master節點。

發布於 2017-02-09
241 條評論
分享
收藏感謝收起

張光宇

none
10 人贊同了該回答
先說Redis的特點

Redis 有各種豐富的數據結構,如果和業務對口,用起來會非常方便(比如Timeline, JobQueue等場合)。
Redis支持數據持久化,雖然無法像資料庫那樣完善,但對於互聯網這種場景,完全夠用了。

Memcached的特點
純粹的cache,意思是一般只會expire cache而不會修改(或append)cache。區別就在於,你fetch的時候總會考慮cache missing的情況。
作為cache時,關於性能比較
兩者都經過了良好的設計,在0~300個client的並發GET/SET下,throughput 都在保持在10萬/秒以上。
memcached的性能比redis要好很多(數倍),這也比較容易理解。但往往瓶頸會在client或者網路等地方。

這里是benchmark

8. 《Redis實戰》epub下載在線閱讀,求百度網盤雲資源

《Redis實戰》(Josiah L. Carlson)電子書網盤下載免費在線閱讀

資源鏈接:

鏈接:https://pan..com/s/1-Az-ADYGqw5PvzUltWuy1g

提取碼:g5kj

書名:Redis實戰

作者:Josiah L. Carlson

譯者:黃健宏

豆瓣評分:8.1

出版社:人民郵電出版社

出版年份:2015-10

頁數:300

內容簡介:

【內容簡介】

本書深入淺出地介紹了Redis的5種數據類型,並通過多個實用示例展示了Redis的用法。除此之外,書中還講述了Redis的優化方法以及擴展方法,是一本對於學習和使用 Redis 來說不可多得的參考書籍。

本書一共由三個部分組成。第一部分對Redis進行了介 紹,說明了Redis的基本使用方法、它擁有的5種數據結構以及操作這5種數據結構的命令,並講解了如何使用Redis去構建文章展示網站、cookie、購物車、網頁緩存、資料庫行緩存等一系列程序。第二部分對Redis命令進行了更詳細的介紹,並展示了如何使用Redis去構建更為復雜的輔助工具和應用程序,並在最後展示了如何使用Redis去構建一個簡單的社交網站。第三部分對Redis用戶經常會遇到的一些問題進行了介紹,講解了降低Redis內存佔用的方法、擴展Redis性能的方法以及使用Lua語言進行腳本編程的方法。

綜上所述, 本書將是一本對於學習和使用 Redis 來說不可多得的參考書籍, 無論是 Redis 新手還是有一定經驗的 Redis 使用者, 應該都能從本書中獲益。

【讀者支持網站】

查看試讀章樣,下載中文注釋源碼或者了解更多關於《Redis實戰》的相關信息,請訪問《Redis實戰》的讀者支持網站: redisinaction.com

作者簡介:

【作者簡介】

在大學畢業之後, Josiah Carlson 博士繼續在加州大學歐文分校學習理論計算機科學。 在學習之餘, Josiah 還斷斷續續地做過一些助教工作, 並偶爾承接一些編程方面的工作。 在 Josiah 即將要研究生畢業的時候, 他發現教職方面的工作機會 並不多, 於是 他加入了 Networks in Motion 公司, 開始了自己的職業生涯。 在 Networks in Motion 公司期間, Josiah 負責開發實時 GPS 導航軟體, 以及交通事故通知系統。

在離開 Networks in Motion 公司之後, Josiah 加入了 Google 公司, 之後他又到了 Adly 公司工作, 並開始學習和使用 Redis 來構建內容定向廣告系統(content-targeting advertising)和 Twitter 分析平台。 幾個月之後, Josiah 加入了 Redis 郵件列表, 並在那裡回答了數百個關於使用和配置 Redis 的問題。 在離開 Adly 公司並成為 ChowNow 公司的首席架構師兼聯合創始人之後不久, Josiah 開始創作這本《Redis 實戰》。

【譯者簡介】

黃健宏(huangz)在 2011 年開始接觸 Redis 以來就一直在學習和研究 Redis , 他從 Redis 2.4 開始閱讀並追蹤 Redis 的源碼, 對 Redis 2.6 以及 Redis 3.0 的源碼進行了詳細的注釋, 並通過分析源碼創作了《Redis 設計與實現》一書。

除此之外, 黃健宏還是 Redis 中文文檔《Redis 命令參考》的譯者。

要了解關於《Redis 實戰》譯者黃健宏的更多信息, 請訪問他的個人主頁 huangz.me ,或者他的豆瓣主頁 http://www.douban.com/people/i_m_huangz/

9. 調用redis時出現java.lang.IllegalArgumentException: hostname can't be null這個錯

當我們執行如下JedisPool類實例的getResource()時拋出can't get a resource異常。

異常代碼如下:

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

at redis.clients.util.Pool.getResource(Pool.java:22)

分析:

redis.clients.util.Pool.getResource會從JedisPool實例池中返回一個可用的redis連接。分析源碼可知JedisPool extends redis.clients.util.Pool<Jedis> .而Pool<T>是通過

commons-pool開源工具包中的org.apache.commons.pool.impl.GenericObjectPool來實現對Jedis實例的管理的。所以我們分析一下GenericObjectPool或許能找到答案。
首先看一下common-pool的api:http://commons.apache.org/pool/apidocs/index.html?org/apache/commons/pool/impl/GenericObjectPool.html。
其中三個重要個幾個屬性是:
MaxActive: 可用連接實例的最大數目,為負值時沒有限制。
MaxIdle: 空閑連接實例的最大數目,為負值時沒有限制。Idle的實例在使用前,通常會通過org.apache.commons.pool.BasePoolableObjectFactory<T>的activateObject()方法使其變得可用。
MaxWait: 等待可用連接的最大數目,單位毫秒(million seconds)。
(注:pool.getResource()方法實際調用的GenericObjectPool類borrowObject()方法,該方法會根據MaxWait變數值在沒有可用連接(idle/active)時阻塞等待知道超時,具體含義參看api。)

也就是說當連接池中沒有active/idle的連接時,會等待maxWait時間,如果等待超時還沒有可用連接,則拋出Could not get a resource from the pool異常。所以為避免這樣的錯誤,

我們應該根據程序實際情況合理設置這三個參數的值,同時在我們獲取一個連接的程序方法中也應該合理的處理這個異常,當沒有連接可用時,等待一段時間再獲取也許是個比較好的選擇。

熱點內容
買車哪些配置必備 發布:2024-05-02 07:30:20 瀏覽:52
華為手機的自帶鈴聲文件夾 發布:2024-05-02 07:20:14 瀏覽:501
xp系統開機密碼怎麼設置 發布:2024-05-02 06:49:48 瀏覽:759
柱加密區公式 發布:2024-05-02 06:40:19 瀏覽:4
java位元組轉換 發布:2024-05-02 06:40:11 瀏覽:687
用c語言做的程序 發布:2024-05-02 06:26:10 瀏覽:325
解壓用流量 發布:2024-05-02 06:21:46 瀏覽:316
雲購源碼系統 發布:2024-05-02 06:12:52 瀏覽:105
電腦如何進行安卓升級 發布:2024-05-02 06:10:08 瀏覽:37
元龍第5集免費看完整版緩存 發布:2024-05-02 06:03:47 瀏覽:668