一、Redis是什麼
1)Redis是REmote DIctionary Server的縮寫,是一個key-
value存儲系統
2)Redis提供了一些豐富的數據結構,包括Strings,Lists,
Hashes,
Sets和Ordered Sets以及Hashes。
包括對這些數據結
構的操做支持
3)Redis能夠替代Memcached,而且解決了斷電後數據徹底丟
失的問題
Download, extract and compile Redis with:
$ wget http://download.redis.io/releases/redis-3.2.5.tar.gz
$ tar xzf redis-3.2.5.tar.gz
The binaries that are now compiled are available in the src directory:Run Redis with:
You can interact with Redis using the built-in client:
三、Redis優勢
1)性能極高,Redis能支持10萬每秒的讀寫頻率
2)豐富的數據類型及對應的操做
3)Redis的全部操做都是原子性的,同時Redis還支
持對幾個操做合併後的原子性執行,也即支持事
務
4)豐富的特性,Redis還支持publish/subscribe,
key過時等特性
在50個併發的狀況下請求10W次,寫的速度是11W次/s,讀的速
度是8.1w次/s
3)Linux2.6 Xeon X3320 2.5GHz的服務器上
4)經過本機的loopback interface接口上執行
redis經常使用五種數據類型:string,hash,list,set,sorted set
Redis內部使用一個redisObject對象來表示全部的key和value,redisObject最主要的信息如上圖所示:
type表明一個value對象具體是何種數據類型,encoding是不一樣數據類型在redis內部的存儲方式,好比:
type=string表明value存儲的是一個普通字符串,那麼對應的encoding能夠是raw或者是int,若是是int
則表明實際redis內部是按數值型類存儲和表示這個字符串的
String是最經常使用的一種數據類型,普通的key/value存儲
String在redis內部存儲默認就是一個字符串,被redisObject所引用,當遇到incr,
decr等操做時會轉成數值型進行計算,此時redisObject的encoding字段爲int
好比,咱們存儲供應商酒店價格的時候能夠採起此結構,用酒店編碼做爲Key,
RatePlan+RoomType做爲Filed,價格信息做爲Value
Hash對應Value內部實際就是一個HashMap,實際這裏會有2種不一樣實現,這個Hash
的成員比較少時Redis爲了節省內存會採用相似一維數組的方式來緊湊存儲,而不
會採用真正的HashMap結構,對應的value redisObject的encoding爲zipmap;當成
員數量增大時會自動轉成真正的HashMap,此時encoding爲ht
lpush,rpush,lpop,rpop,lrang等
Redis list應用場景很是多,也是Redis最重要的數據結構之一,好比twitter的關注
列表,粉絲列表等均可以用Redis的list結構來實現
Redis list的實現爲一個雙向鏈表,便可以支持反向查找和遍歷,更方便操做,不過
帶來了部分額外的內存開銷,Redis內部的不少實現,包括髮送緩衝隊列等也都是
用的這個數據結構
sadd,spop,smembers,sunion 等
Set對外提供的功能與list相似,當你須要存儲一個列表數據,又不但願出現重複
數據時,set 是一個很好的選擇,而且set提供了判斷某個成員是否在一個set集合
內的接口,這個也是list所不能提供的
Set 的內部實現是一個value永遠爲null的HashMap,實際就是經過計算hash的方
式來快速排除重複的,這也是set能提供判斷一個成員是否在集合內的緣由
Sorted set的使用場景與set相似,區別是set不是自動有序的,而sorted set能夠
經過用戶額外提供一個優先級(score)的參數來爲成員排序,而且是插入有序的,
即自動排序.當你須要一個有序的而且不重複的集合列表,那麼能夠選擇sorted
set數據結構
Sorted set的內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,
HashMap裏放的是成員到score的映射,而跳躍表裏存放的是全部的成員,排序依據
是HashMap裏存的score,使用跳躍表的結構能夠得到比較高的查找效率
Redis爲不一樣數據類型分別提供了一組參數來控制內存使用,咱們在前面提到過Redis Hash的value內部
是一個HashMap,若是該Map的成員數比較少,則會採用一維數組的方式來緊湊存儲該Map,即省去了大量指
針的內存開銷,這個參數在redis.conf配置文件中下面2項:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
含義是當value這個Map內部不超過多少個成員時會採用線性緊湊格式存儲,默認是64,即value內部有64
個如下的成員就是使用線性緊湊存儲,超過該值自動轉成真正的HashMap
hash-max-zipmap-value 含義是當value這個Map內部的每一個成員值長度不超過多少字節就會採用線性緊
湊存儲來節省空間
以上2個條件任意一個條件超 過設置值都會轉換成真正的HashMap,也就不會再節省內存了,那麼這個值是
不是設置的越大越好呢,答案固然是否認的,HashMap的優點就是查找和操做的時間複雜度都是O(1)的,而
放棄Hash採用一維存儲則是O(n)的時間複雜度,若是成員數量不多,則影響不大,不然會嚴重影響性能,所
以要權衡好這個值的設置,整體上仍是時間成本和空間成本上的權衡
Redis的發佈/訂閱(Publish/Subscribe)功能類
似於傳統的消息路由功能,發佈者發佈消息,訂閱
者接收消息,溝通發佈者和訂閱者之間的橋樑是
訂閱的Channel或者Pattern
訂閱者和發佈者之間的關係是鬆耦合的,發佈者
不指定哪一個訂閱者才能接收消息,訂閱者不僅接
收特定發佈者的消息
Redis能夠按key設置過時時間,過時後將被自動
刪除,這個特性讓Redis很適合用來存儲酒店動態
流量和價格信息
用TTL命令能夠獲取某個key值的過時時間,-1表
示不會過時
Redis目前對事務支持還比較簡單,也即支持一些
簡單的組合型的命令,只能保證一個client發起
的事務中的命令能夠連續的執行,而中間不會插
入其餘client的命令:因爲Redis是單線程來處
理全部client的請求的因此作到這點是很容易
的
事務的執行過程當中,若是redis意外的掛了,這時
候事務可能只被執行了一半,能夠用redis-
check-aof 工具進行修復
數據快照的原理是將整個Redis內存中存的全部
數據遍歷一遍後,保存到一個擴展名爲rdb的數據文件
中。經過SAVE命令能夠調用這個過程
以上在redis.conf中的配置指出在多長時間內,有
多少次更新操做,就將數據同步到數據文件,這個
能夠多個條件配合.上面的含義是900秒後有一個
key發生改變就執行save,300秒後有10個key發生
改變執行save,60秒有10000個key發生改變執行
save
10.1 數據快照的缺點是持久化以後若是出現
crash則會丟失一段數據,所以做者增長了另外
一種追加式的操做日誌記錄,叫append only
file,其日誌文件以aof結尾,咱們通常稱爲aof文
件。要開啓aof日誌的記錄,須要在配置文件中進
行以下設置:
10.2 appendonly配置若是不開啓,可能會在斷電時致使一段
時間內的數據丟失。由於redis自己同步數據文件是按save條
件來同步的,因此有的數據會在一段時間內只存在於內存中
appendfsync no/always/everysec
2)always:表示每次更新操做後手動調用fsync() 將數據寫
到磁盤
3)everysec:表示每秒同步一次。通常用everysec
10.3 AOF文件只增不減會致使文件愈來愈大,重寫過程以下
3)父子進程是並行執行的,在子進程遍歷並寫臨時文件的時
候,父進程在照常接收請求,處理請求,寫AOF,不過這時他是
把新來的AOF寫在一個緩衝區中
4)子進程寫完臨時文件後就會退出.這時父進程會接收到子
進程退出的消息,他會把本身如今收集在緩衝區中的全部AOF
追加在臨時文件中
5)最後把臨時文件rename一下,更名爲appendonly.aof, 這
時原來的aof文件被覆蓋。整個過程完成
當Redis服務器掛掉時,重啓時將按如下優先級恢復數據到內
存中:
1)若是隻配置了AOF,重啓時加載AOF文件恢復數據
2)若是同時配置了RBD和AOF,啓動時只加載AOF文件恢復數據
3)若是隻配置了RDB,啓動時將加載dump文件恢復數據
十二、Redis主從複製
Master Redis Server Port:6379
Slave配置很簡單,只須要在slave服務器的redis.conf加入:
slaveof 175.41.209.118 6379
啓動master和slave,而後寫入數據到master,讀取slave,可
以看到數據被複制到slave了
配置好slave後,slave與master創建鏈接,而後發送sync命令。
不管是第一次鏈接仍是從新鏈接,master都會啓動一個後臺
進程,將數據庫快照保存到文件中,同時master主進程會開始
收集新的寫命令並緩存;後臺進程完成寫文件後,master就
發送文件給slave,slave將文件保存到硬盤上,再加載到內存
中, 接着master就會把緩存的命令轉發給slave,後續master
將收到的寫命令發送給slave;若是master同時收到多個
slave發來的同步鏈接命令,master只會啓動一個進程來寫數
據庫鏡像, 而後發送給全部的slave
2)多個slave能夠鏈接同一個master外,還能夠鏈接到其餘
slave
3)主從複製不會阻塞master,在同步數據時,master能夠繼續
處理client請求
4)能夠在master禁用數據持久化,註釋掉master配置文件中的
全部save配置,只需在slave上配置數據持久化
官方提供了一個數據, Slave在21秒即完成了對
Amazon網站 10G key set的複製
13.1 Redis的客戶端很是豐富,幾乎全部流行的
語言都有客戶端
客戶端列表:http://redis.io/clients
Java客戶端推薦Jedis: https://github.
com/xetorthio/jedis
13.2 Jedis目前Release版本是3.2.5,支持的特性以下,一句話歸納,該有的都有了,不應有的也有了
• Commands operating on any kind of values
• Commands operating on string values
• Commands operating on hashes
• Commands operating on lists
• Commands operating on sets
• Commands operating on sorted sets
• Persistence control commands
• Remote server control commands
• Sharding (MD5, MurmureHash)
• Sharding with pipelining
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
Jedis jedis = new Jedis("localhost");
String value = jedis.get("foo");
14.1 目前,Redis server沒有提供shard功能,只能
在client端實現
Redis有些客戶端實現了shard,好比Java客戶端
Jedis.
JedisPool,JedisPoolConfig,JedisSharedInfo,
ShardedJedisPool等相關類來使用shared功能
14.2 Jedis shardedJedisPool的建立例子
<bean id="dataJedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="200"/>
<property name="maxIdle" value="200"/>
<property name="maxWait" value="1000"/>
<property name="testOnBorrow" value="true"/>
<bean id="dataJedisShardInfo" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.host}"/>
<constructor-arg index="1" value="${redis.port}"/>
<constructor-arg index="2" value="10000"/>
<bean id="dataShardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="dataJedisPoolConfig"/>
<constructor-arg index="1">
<ref bean="dataJedisShardInfo"/>
14.3 Jedis shardedJedisPool的使用
ShardedJedis shardedJedis = shardedJedisPool.getResource();
shardedJedisPool.returnResource(shardedJedis);
穩定版本的redis(2.4.5)只支持簡單的
master-slave replication: 一個master寫,多
個slave讀。只能經過客戶端一致性哈希本身作
sharding
Redis cluster是下一階段最重要的功能之一,會
有集羣的自動sharding,多節點容錯等:集羣功
將在3.0版本推出
1六、Redis Use In ChoiceHotels
16.1 Choice的Redis Server是一主一從,使用亞馬
遜AWS虛擬機,機器配置以下:
4 EC2 Compute Units (2 virtual cores with 2
16.2 現狀:天天約更新30萬左右的數據,如今庫裏有400W條紀
錄(400W個Key,使用的是Hash結構存儲),每條數據都設有過
期時間,佔用了2.5G的內存
爲了提升讀寫性能Master關閉了Persistence功能,Slave只
負責同步備份Master的數據,不對外提供服務
另外一種可選方案是用Master提供寫服務,Slave提供讀服務來
實現讀寫分離
16.3 Master開啓Save功能的影響:在dump過程當中,除了磁盤有
大量的IO操做之外,Redis是fork一個子進程來dump數據到硬
盤,原有進程佔用30%+的CPU,dump數據的子進程單獨另外佔
用一個CPU
Master開啓Save對性能的直接影響:TPS大概減小
30%
Choice Master Redis服務器開啓Save功能後的明顯影響是:
機器Load一直居高不下,大量請求超時:關閉Save功能後服
務器壓力銳減,基本無請求超時狀況發生
16.4 Redis開啓AOF日誌功能的影響:對性能有影
響,可是因爲每次追加的數據量小,因此對性能的
影響相對小不少
Choice Master Reids開啓AOF功能後,機器load
微升,對性能無明顯影響
16.5 bgrewriteaof對性能的影響:爲了定時減少
AOF文件的大小,Redis2.4之後增長了自動的
bgrewriteaof的功能,Redis會選擇一個自認爲負
載低的狀況下執行bgrewriteaof,這個重寫AOF文
件的過程是很影響性能的
Choice Master開啓自動bgrewriteaof功能對系
統的明顯影響是:高併發時段有請求超時,機器
load 明顯上升幾倍
16.6 目前較好的方案是:Mater關閉Save功能,關
閉AOF日誌功能,以求達到性能最佳:Slave開啓
Save並開啓AOF日誌功能,並開啓bgrewriteaof
功能,不對外提供服務,這樣Slave的負載整體上
會一直略高於Master負載,但Master性能達到最
好
從目前使用的狀況來看,整體效果仍是比較理想
的, ChoiceHotels的價格存儲使用Redis的Hash
結構也很是適合,HotelCode+Date最爲key, 這樣
的key很容易設置過時,RatePlan+RoomType做爲
Filed, 價格和流量是Value
目前天天從GTA到Choice大約500w個請求,整個
過程80%的請求在500毫秒內返回,基本無超時現
象發生
used_memory_peak_human:2.46G
aof_current_size:3874203906
db0:keys=4073286,expires=4073286