Redis学习整理
redis幾種數據類型
1.字符串(string)
2.列表(list)
3.集合(set)
4.哈希(hash)
5.有序集合(zset)
1.字符串
字符串類型是Redis中最基本的數據類型,String可以存儲任何形式的字符串,包括二進制數據。
一個string類型允許存儲的數據最大容量是512MB。
set 設置指定key的值
語法:set key value
127.0.0.1:6379 > set name zhaoliu OK 127.0.0.1:6379 > set name "li si" OK- set 設置給定key的值。如果key已存儲其他值,則覆蓋舊值
- 如果有空格等其他字符,則使用引號包含。
get 獲取指定key的值
語法:get key
127.0.0.1:6379 > get name "li si" # 獲取不存在的key 127.0.0.1:6379> get name1 (nil)# 獲取不是String類型的key 127.0.0.1:6379> lpush a '111' (integer) 3 127.0.0.1:6379> get a (error) WRONGTYPE Operation against a key holding the wrong kind of value- 獲取指定key的值,如果key不存在,則返回nil,如果key存儲的值不是String類型,則返回錯誤
mset 設置一個或多個key-value對
語法:mset key1 value1 key2 value2
127.0.0.1:6379> mset keya valuea keyb valueb OK# 設置已經存在的key 127.0.0.1:6379> mset keya 'i ma a' keyb 'i am b' OK- 如果key存在,則新值覆蓋舊值 (和set一樣)
mget獲取一個或者多個給定key的值
# 獲取一個key的值 127.0.0.1:6379> mget keya 1) "i ma a"# 獲取多個key的值 127.0.0.1:6379> mget keya keyb 1) "i ma a" 2) "i am b"**setnx key不存在時設置key的值 **
127.0.0.1:6379> setnx age 18 (integer) 1# key存在,設置不成功,返回0 127.0.0.1:6379> setnx name 'xiao bai' (integer) 0 127.0.0.1:6379> get name "wang wu"- 只能用于設置不存在的key
msetnx 設置一個或多個key-value對,當且僅當所有key不存在
語法:msetnx key1 value1 key2 value2 …
127.0.0.1:6379> msetnx a1 10 a2 20 (integer) 1# 存在key,設置不成功 127.0.0.1:6379> msetnx num 10 age 10 (integer) 0- 設置多個key時,只要其中一個key存在,則所有的值設置失敗
getset 設置指定key的值,并返回舊值
127.0.0.1:6379> getset name 'wang wu' "li si"127.0.0.1:6379> get name "wang wu"# key不存在,返回nil 127.0.0.1:6379> getset aa 'i am aa' (nil)- 當key不存在時,返回nil
- 當key不是字符串時,報錯
**setrange為指定的key進行指定范圍value值,從offset處開始重寫 **
語法:setrange key offset value
127.0.0.1:6379> getset name 'wang wu' "li si"127.0.0.1:6379> get name "wang wu"# key不存在,返回nil 127.0.0.1:6379> getset aa 'i am aa' (nil)getrange獲取指定在key中指定范圍(偏移量)的字符串
語法:getrange key start end
127.0.0.1:6379> get keya "i ma a hello" 127.0.0.1:6379> getrange keya 0 -1 "i ma a hello"# 獲取keya中hello 127.0.0.1:6379> getrange keya 7 -1 "hello" 127.0.0.1:6379> getrange keya 7 12 "hello"append為指定的key追加值
語法:append key value
# 已存在的key 127.0.0.1:6379> append keya ' hello' (integer) 12 127.0.0.1:6379> get keya "i ma a hello"# 不存在的key 127.0.0.1:6379> append name 'li si' (integer) 5 127.0.0.1:6379> get name "li si"- 若key存在,則將value追加到原來的key值的末尾
- 若key不存在,則進行設置該key的值為value,可以理解為執行set操作
strlen獲取指定key中值的長度
語法:strlen key
127.0.0.1:6379> strlen keya (integer) 12# key不存在,返回0 127.0.0.1:6379> strlen ziruchu (integer) 0# key不是字符串時報錯 127.0.0.1:6379> lpush db mysql redis (integer) 2 127.0.0.1:6379> strlen db (error) WRONGTYPE Operation against a key holding the wrong kind of value- 只能獲取key類型為字符串的值的長度,否則報錯
- 當key不存在時,返回0
incr將key中存儲的數字值增1
語法:incr key
127.0.0.1:6379> incr num (integer) 1 127.0.0.1:6379> incr num (integer) 2# key中的值不是數字類型 127.0.0.1:6379> incr name (error) ERR value is not an integer or out of range- key不存在,則進行設置,并且值為1;如果key的值不是數字類型,則報錯
decr將key中存在的數字值減1
語法:decr key
127.0.0.1:6379> incr num (integer) 1 127.0.0.1:6379> incr num (integer) 2# key中的值不是數字類型 127.0.0.1:6379> incr name (error) ERR value is not an integer or out of rangeincrby 將指定key的值加上給定的增量值
語法:incrby key 數字值
127.0.0.1:6379> incr num (integer) 1 127.0.0.1:6379> incr num (integer) 2# key中的值不是數字類型 127.0.0.1:6379> incr name (error) ERR value is not an integer or out of rangedecrby 將指定key的值減去給定的額增量值
語法:decrby key 數字值
127.0.0.1:6379> decrby num3 2 (integer) 8# key不存在 127.0.0.1:6379> decrby num4 10 (integer) -10 # key中值不是數值型 127.0.0.1:6379> decrby name 10 (error) ERR value is not an integer or out of rangeincrbyfloat將key所存儲的值加上給定的浮點增量值
語法:incrybyfloat key 增量值
127.0.0.1:6379> get num "1" 127.0.0.1:6379> incrbyfloat num 5.5 "6.5" 127.0.0.1:6379> incrbyfloat num 5 "11.5"# 不存在的key 127.0.0.1:6379> incrbyfloat num10 10.1 "10.1"# 不是數字值 則報錯 127.0.0.1:6379> get name "wang hello" 127.0.0.1:6379> incrbyfloat name 5.5 (error) ERR value is not a valid floatsetex 為指定的key設置過期時間
語法:setex key 時間(秒)value
127.0.0.1:6379> setex db 60 db # 查看過期時間 127.0.0.1:6379> ttl db (integer) 56# 不存在的key,相當于set,并設置過期時間 127.0.0.1:6379> setex db 10 mysql OK # 替換舊值并設置過期時間 127.0.0.1:6379> setex age 60 19 OK 127.0.0.1:6379> get age "19"- key存在,則舊值替換新值;key不存在,則設置值并設置過期時間
psetex 以毫秒為單位設置key的有效時間
語法:psetex key 毫秒值 value
127.0.0.1:6379> psetex gender 10000 nan OK位操作
一個字節由8個二進制位組成。redis有4個位操作命令setbit,getbit,bitcount,bittop;
# 設置一個鍵值對 127.0.0.1:6379> set foo bar OKbar這3個字母分別對應的ASCLL為98,97,114,轉成二進制分別為01100010,01100001,01110010
| 01100010 | 01100001 | 01110010 |
getbit獲取key中值指定偏移量的位(bit),偏移量索引從0開始
語法:getbit key 偏移量
getbit命令 獲取一個字符串類型鍵指定位置的二進制位的值(0或者1),索引從0開始
# 獲取bar的第0位,也是b的ASSIC二進制的第一個數字 127.0.0.1:6379> getbit foo 0 (integer) 0 127.0.0.1:6379> getbit foo 1 (integer) 1 127.0.0.1:6379>- 獲取二進制位的索引超過鍵值的二進制位的實際長度則默認值為0
setbit 對key中值設置或清除指定偏移量上的位
語法:setbit key偏移量 value
# 設置bar中b對應的二進制位,從0開始數,也是第7個數,從1改0 127.0.0.1:6379> setbit foo 6 0 (integer) 1- 若設置的位置超過了二進制位的長度,setbit命令自動將中間的二進制位設置為0
- 設置一個不存在的鍵指定的二進制位值會自動將前面的位賦值為0
bitcount獲取字符串類key中值是1的二進制位個數
語法:bitcount key [start end]
1)獲取所有二進制為1的總數
127.0.0.1:6379> bitcount foo (integer) 11 127.0.0.1:6379> bitcount foo 0 -1 (integer) 112)獲取前2個字節指定范圍內二進制為1的總數
127.0.0.1:6379> bitcount foo 0 1 (integer) 7bittop對字符串key進行位運算,并將結果存儲在指定key中
語法:bittop 位運算符 結果存儲鍵 key [key1 key2 …]
參數解釋:
位運算符有:AND,OR,XOR,NOT
127.0.0.1:6379> set foo1 bar OK 127.0.0.1:6379> set foo2 aar OK 127.0.0.1:6379> bitop OR result foo1 foo2 (integer) 3 127.0.0.1:6379> get result "car"哈希(Hash)
-
Redis是采用字典結構以鍵值對的形式存儲數據的。
-
哈希類型的鍵值也是一種字典結構,存儲了字段和字段值的映射,字段值只能是字符串,不支持其他數據類型。
-
哈希類型不能嵌套其他數據類型。
-
一個 哈希類型鍵可以包含至多2^32-1個字段。
-
哈希類型適合存儲對象 :使用對象類別和ID構成鍵名,使用字段表示對象的屬性,字段值則存儲屬性值。
如下案例:存儲ID為1的文章對象,分別使用作者,時間,內容這3個字段 來存儲文章的信息
hset 將哈希表 中key的field的值設置為value
語法:hset key field value
# hset設置單個值 127.0.0.1:6379> hset car price 10000 (integer) 1 127.0.0.1:6379> hset car name BMW (integer) 1 # 字段已存在,執行更新操作,返回0 127.0.0.1:6379> hset car name BMWM (integer) 0- 若hash不存在 ,則創建;若字段已存在,則新值覆蓋舊值。
- hset不區分插入還是更新操作,當執行插入操作時(字段不存在),hset命令返回1;當執行更新操作時(字段存在),hset命令返回0。鍵不存在時,hset會自動創建該鍵。
hget獲取 哈希表 中的值
127.0.0.1:6379> hget car name BMWMhmset 將多個field-value對設置到哈希表key中
語法:hmset key field1 value1 [ field2 value2]
127.0.0.1:6379> hmset cat color white age 2 OKhmget 獲取哈希表指定字段的值
語法:hmget key field1 [field2,field3…]
127.0.0.1:6379> hmget cat color age 1) "white" 2) "2hgetall獲取指定哈希表指定key的所有字段和值
語法:hgetall key
127.0.0.1:6379> hgetall cat 1) "color" 2) "white" 3) "age" 4) "2"hexists判斷一個字段是否存在
語法:hexists key field
127.0.0.1:6379> hexists cat age (integer) 1 127.0.0.1:6379> hexists cat a (integer) 0- hexists 判斷hash表中一個字段是否存在,存在返回1,不存在返回0
hdel刪除一個或多個字段
語法:hde1 key field1 [field2 …]
127.0.0.1:6379> hdel car name (integer) 1 127.0.0.1:6379> hdel cat color age (integer) 2- 返回刪除字段的個數
hkeys 獲取一個Hash表中所有字段
語法:hkeys key
127.0.0.1:6379> hkeys article 1) "author" 2) "time"hvalues獲取一個Hash表中所有的值
語法:hvalues key
127.0.0.1:6379> hvals article 1) "ziruchu" 2) "2020"hlen獲取字段數量
語法:hlen key
127.0.0.1:6379> hlen article (integer) 2hincrby為哈希表key中指定字段的整數值加上增量值
語法:hincrby key field 增量值
127.0.0.1:6379> hmset number id 1 total 3 OK127.0.0.1:6379> hincrby number id 10 (integer) 11hincrbyfloat為哈希表key中指定字段的浮點數加上增量值
語法:hincrbyfloat key field 增量值
127.0.0.1:6379> hincrbyfloat number total 10.34 "13.34"hscan 根據鍵迭代哈希表中的鍵值對
語法: hscan key cusssor [match pattern] [count count]
參數: cursor 游標 pattern 匹配模式 count指定從數據集返回多少元素,默認10
127.0.0.1:6379> hscan car 0 MATCH "p*" COUNT 1 1) "0" 2) 1) "price"2) "1001"3) "produce"4) "china"列表
列表(list)類型可以存儲一個有序的字符串列表。常用操作 是向列表兩端添加元素,或者獲得列表的某個片段。
列表類型內部使用雙向鏈表實現,因此向兩端添加元素的時間復雜度為O(1),獲得越近兩端的元素越快
缺點 :通過索引訪問元素比較慢
經典使用場景: 微博上的熱搜等有時效的內容
lpush 將一個或者多個值插入列表頭部
語法: lpush key value [value1 value2 …]
127.0.0.1:6379> lpush nunber 1 (integer) 1 127.0.0.1:6379> lpush number 2 3 (integer) 2- lpush 向列表左邊增加元素
lpop從列表左邊彈出一個元素并顯示該值
語法:lpop key
127.0.0.1:6379> lpop number "3"rpush向列表右邊增加一個或者多個值
語法:rpush key value1 [value2 …]
127.0.0.1:6379> rpush number 0 -1 (integer) 5rpop從列表右邊彈出一個元素并顯示該值
語法:rpop key
127.0.0.1:6379> rpop number "-1"llen獲取列表中元素的個數
語法:llen key
127.0.0.1:6379> rpop number "-1" 127.0.0.1:6379> rpop nunber (nil)- key不存在返回nil
lrange獲取指定范圍的元素
語法:lrange key start end
# 獲取所有元素 127.0.0.1:6379> lrange number 0 -1 1) "2" 2) "1" 3) "0"# 獲取前2個元素 127.0.0.1:6379> lrange number 0 1 1) "2" 2) "1"- 若start索引位置比end索引位置靠后,則返回空列表
- 若end大于實際索引范圍,則返回列表最右邊的元素
lrem刪除列表中指定的值
語法:lrem key count value
127.0.0.1:6379> rpush number 2 (integer) 4 127.0.0.1:6379> lrange number 0 -1 1) "2" 2) "1" 3) "0" 4) "2"# 從右邊開始刪除值為2的元素 127.0.0.1:6379> lrange number 0 -1 1) "2" 2) "1" 3) "0" 4) "2" 127.0.0.1:6379> lrem number -1 2 (integer) 1 127.0.0.1:6379> lrange number 0 -1 1) "2" 2) "1" 3) "0"lrem刪除列表中前count個值為value的元素,返回實際刪除元素的個數。count值不同,lrem命令執行方式也不同
- 當count > 0時,lrem命令從列表左邊開始刪除前count個值為value的元素
- 當count <0 時,lrem命令從列表右邊開始刪除前count個值為value的元素
- 當count=0時,lrem命令會刪除所有值為value的元素
lindex通過索引獲取列表中的元素
語法:lindex key index
127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "1" 4) "3" 5) "2" 6) "2" 127.0.0.1:6379> lindex number 5 "2" 127.0.0.1:6379> lindex number 3 "3"lset通過索引設置列表元素的值
# 列表元素中索引為1的值設置為10 127.0.0.1:6379> lset number 1 10 OKltrem只保留列表指定片段的元素
語法:ltrim key start stop
127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "1" 4) "3" 5) "2" 6) "2" 127.0.0.1:6379> ltrim number 1 5 OK 127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "3" 4) "2" 5) "2"- ltrim可以刪除指定元素之外的所有元素
linsert在列表的元素前或后插入元素
語法:linsert key before|after pivot value
127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "3" 4) "2" 5) "2" 127.0.0.1:6379> linsert number before 2 4 (integer) 6 127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "3" 4) "4" 5) "2" 6) "2" 127.0.0.1:6379> linsert number after 2 4 (integer) 7 127.0.0.1:6379> 127.0.0.1:6379> lrange number 0 -1 1) "1" 2) "1" 3) "3" 4) "4" 5) "2" 6) "4" 7) "2"- linsert 現在列表中從左到右查找值為pivot的元素,然后根據第二個參數是before|after來決定將value值插入到該元素前還是后
rpoplpush 將元素從一個列表轉到另一個列表
語法:rpoplpush source destination timeout
127.0.0.1:6379> rpoplpush nunber number "a" 127.0.0.1:6379> rpoplpush nunber number "b" 127.0.0.1:6379> lrange number 0 -1 1) "b" 2) "a" 3) "1" 4) "1" 5) "3" 6) "4" 7) "2" 8) "4" 9) "2"- rpoplpush先將source列表類型的右邊彈出一個元素;然后將它加入到destination列表類型的左邊,并返回彈出的元素,整個過程原子性
rpushx為已存在的列表添加值
語法:rpushx key value
127.0.0.1:6379> rpushx number + (integer) 10lpushx將值插入到已存在列表的頭部
語法:lpushx key value
127.0.0.1:6379> lpushx n - (integer) 0 127.0.0.1:6379> lpush nnumber - (integer) 1 127.0.0.1:6379> lrange nmber 0 -1 (empty array) 127.0.0.1:6379> lrange number 0 -11) "b"2) "a"3) "1"4) "1"5) "3"6) "4"7) "2"8) "4"9) "2" 10) "+"blpop移除并獲取列表的第一個元素
語法:blpop key1 [key2] timeout
127.0.0.1:6379> blpop number1 300 1) "number1" 2) "3"- 移除并獲取列表的第一個元素,如果列表沒有元素,會阻塞列表知道等待超時或發現可彈出元素為止
brpop移除并獲取列表的最后一個元素
語法:brpop key1 [key2] timeout
127.0.0.1:6379> brpop number 200 1) "number" 2) "2"**brpoplpush從列表彈出一個值,將彈出的值插入到另一個列表 **
語法:brpoplpush source destination timeout
127.0.0.1:6379> brpoplpush number number1 500 "1"- 從列表中取出最后一個元素,并插入到另外一個列表的頭部;
- 如果 列表中沒有元素會阻塞列表,直到等待超時或發現可彈出元素為止
集合(Set)
集合中每個元素都是不同的,且沒有順序。一個集合類型(Set)鍵可以存儲至多2^32 - 1個字符串。
集合的常用操作時向集合中加入或刪除元素,判斷箢篼是否存在等,由于集合類型在redis內部是使用值為空的hash表實現的,因此這些操作的時間復雜度都是O(1) 。最為方便的是集合類型之間可以進行交集,并集,差集運算。
例如:存儲文章標簽
集合類型和列表類型的對比:
| 有序性 | 否 | 是 |
| 唯一性 | 是 | 否 |
sadd向集合中添加一個或多個元素
語法:sadd key member1 [member2 …]
127.0.0.1:6379> sadd letters a (integer) 1 # 因為a已經存在,所以不會添加 127.0.0.1:6379> sadd letters a b c (integer) 2集合中不能有相同的元素,加入的元素若有重復的,就會忽略這個重復的元素。該命令返回成功加入集合的元素數量
smembers獲取集合中所有元素
語法:smembers key
127.0.0.1:6379> smembers letters 1) "c" 2) "b" 3) "a"srem從集合中刪除一個或多個元素
語法: srem key member1 [members …]
127.0.0.1:6379> smembers letters 1) "c" 2) "b" 3) "a"sismember判斷元素是否在集合中
語法:sismember key member
127.0.0.1:6379> smembers letters 1) "c" 2) "b" 3) "a"sdiff對多個集合執行差集運算
語法:sdiff key1 [key2 key3 …]
127.0.0.1:6379> sadd setA 1 2 3 (integer) 3 127.0.0.1:6379> sadd setB 2 3 4 (integer) 3 127.0.0.1:6379> sdiff setA setB 1) "1" 127.0.0.1:6379> sdiff setB setA 1) "4" 127.0.0.1:6379> sadd setC 2 3 (integer) 2 127.0.0.1:6379> sdiff setA setB setC 1) "1"setA setB setC 差集運算;先算setA - setB,再計算與setC的差集
sinter對多個集合執行交集運算
語法:sinter key1 [key2 …]
127.0.0.1:6379> sinter setA setB 1) "2" 2) "3"127.0.0.1:6379> sinter setA setB setC 1) "2" 2) "3"sunion 對多個集合執行并集運算
語法 :sunion key1 [key2 …]
127.0.0.1:6379> sunion setA setB 1) "1" 2) "2" 3) "3" 4) "4" 127.0.0.1:6379> sunion setA setB setC 1) "1" 2) "2" 3) "3" 4) "4"sdiffscore返回給定所有集合的差集并存儲在destination中
語法:sdiffscore destination key1 [key2 …]
127.0.0.1:6379> sdiffstore new_set setA setB (integer) 1127.0.0.1:6379> smembers new_set 1) "1"將給定集合之間的差集存儲在指定的集合中。如果指定的集合key已存在,則會被覆蓋。
sinterstore返回所有集合的交集并存儲在destination中
語法:sinterstore destination key1 [key2 …]
127.0.0.1:6379> sinterstore new_set1 setA setB (integer) 2127.0.0.1:6379> smembers new_set1 1) "2" 2) "3"suninnstore所有給定集合的并集存儲在destination
語法:sunionstore destination key1 [key2 …]
127.0.0.1:6379> sunionstore setUnionJi setA setB (integer) 4scard獲取集合中成員數量
127.0.0.1:6379> smembers new_set2 1) "1" 2) "2" 3) "3" 4) "4" 127.0.0.1:6379> scard setA (integer) 3 127.0.0.1:6379> scard new_set2 (integer) 4smove將member元素從source集合移到destination集合
語法:smove source destination member
127.0.0.1:6379> sadd name lisi wangwu (integer) 2 127.0.0.1:6379> sadd age 17 18 (integer) 2127.0.0.1:6379> smove age name 17 (integer) 1 127.0.0.1:6379> smembers name 1) "lisi" 2) "17" 3) "wangwu"spop移除并返回集合中的一個隨機元素
語法:spop key [count]
127.0.0.1:6379> smembers name 1) "wangwu" 2) "17" 3) "lisi" 127.0.0.1:6379> 127.0.0.1:6379> spop name "lisi" 127.0.0.1:6379> spop name "17" 127.0.0.1:6379> spop new_set1 2 1) "2" 2) "3" 127.0.0.1:6379> smembers new_set1 (empty array)srendmember返回集合中一個或多個隨機數
語法:srandmember key [count]
127.0.0.1:6379> srandmember setC "3" 127.0.0.1:6379> srandmember setC "2"scan迭代集合中的元素
語法:sscan key cursor [match patrn] [count count]
127.0.0.1:6379> sscan name 0 match w* 1) "0" 2) 1) "wangwu"有序集合(sorted set)
Redis有序集合和集合一樣也是string類型元素的集合,并且不允許重復的成員
不同的是每個元素都會關聯一個double類型的分數。redis通過分數來為集合中的成員進行從小到大的排序
有序集合的成員是唯一的,但分數(score)卻可以重復。
有序集合使用跳躍表和Hash實現,所以添加刪除查找的復雜度都是O(1)。 集合中最大的成員數為 2^32 - 1
使用場景 : 根據用戶權重搶購商品 (優先級消息隊列,先來先),學生成績排名…
zadd向集合中添加一個或多個元素和該元素的分數
語法:zadd key score1 member1 [score2 member2 …]
127.0.0.1:6379> zadd board 89 tom 60 peter 100 hipi (integer) 3# 修改分數 127.0.0.1:6379> zadd board 87 hipi (integer) 0zscore獲取元素分數
語法:zscore key member
127.0.0.1:6379> zscore board hipi "87"zrange 獲取排名在某個范圍的元素列表
語法:zrange key start stop [withscores]
127.0.0.1:6379> zrange board 0 -1 1) "peter" 2) "hipi" 3) "tom" 127.0.0.1:6379> zrange board 0 2 1) "peter" 2) "hipi" 3) "tom"127.0.0.1:6379> zrange board 0 -1 withscores 1) "peter" 2) "60" 3) "hipi" 4) "87" 5) "tom" 6) "89"zrange按照分數值從大到小排序。下標參數start和stop都是以0為底
zrevrange返回有序集合中指定區間內的成員,通過索引 ,分數由高到低
語法:zrevrange key start top [withscores]
127.0.0.1:6379> zrevrange board 0 -1 1) "tom" 2) "hipi" 3) "peter"其中成員的位置按照分數值遞減來排列
zrevrangebyscore返回有序集合中指定分區區間內的成員,分數從高到低排序
語法 :zrevrangebyscore key max min [withscores]
127.0.0.1:6379> zrevrange board 0 -1 1) "tom" 2) "hipi" 3) "peter"zincrby 增加某個元素的分數
語法:zincrby key increment member
# 返回值為更改后的分數 127.0.0.1:6379> zincrby board 4 jerry "60"zcard獲取集合中元素的數量
語法:zcard key
# 返回值為更改后的分數 127.0.0.1:6379> zincrby board 4 jerry "60"zcount獲取集合中元素的數量
語法:zcount key min max
127.0.0.1:6379> zcount board 90 100 (integer) 1zrem刪除一個或者多個元素
語法:zrem key member [member1 member2 …]
127.0.0.1:6379> zrem board tom (integer) 1zremrangebyrank按照排名范圍刪除元素
127.0.0.1:6379> zadd testrem 1 a 2 b 3 c 4 d 5 f 6 g (integer) 6 127.0.0.1:6379> zremrangebyrank testrem 0 1 (integer) 2 127.0.0.1:6379> zrange testrem 0 -1 1) "c" 2) "d" 3) "f" 4) "g"zremrangebyscore按照分數范圍刪除元素
語法 :zremrangebyscore key min max
127.0.0.1:6379> zremrangebyscore testrem 2 4 (integer) 2 127.0.0.1:6379> zrange testrem 0 -1 withscores 1) "f" 2) "5" 3) "g" 4) "6"zrank獲取元素的排名
語法:zrank key member
127.0.0.1:6379> zrank board hipi (integer) 5按照元素分數從小到大的順序獲得指定的元素排名(從0開始)
zinterstore 計算有序集合的交集
語法:zinterstore destination numkeys key1 [key2 …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
解釋:該命令用來計算多個有序集合的交集并將結果存儲在destination鍵中,返回值為destination鍵中元素個數;
127.0.0.1:6379> zadd sort1 1 a 2 b (integer) 2 127.0.0.1:6379> zadd sort2 10 a 20 b (integer) 2 127.0.0.1:6379> zinterstore storeResult 2 sort1 sort2 (integer) 2 127.0.0.1:6379> zrange sorteResult 0 -1 withscores (empty array) 127.0.0.1:6379> zrange storeResult 0 -1 withscores 1) "a" 2) "11" 3) "b" 4) "22"zunionstore極端一個或者多個集合的并集
語法:zunionstore destination numbers key1 [key2 …]
127.0.0.1:6379> zunionstore uresult 2 sort1 sort2 (integer) 2 127.0.0.1:6379> zrange uresult 0 -1 1) "a" 2) "b" 127.0.0.1:6379> zrange uresult 0 -1 withscores 1) "a" 2) "11" 3) "b" 4) "22" 127.0.0.1:6379> zrange sort1 0 -1 withscores 1) "a" 2) "1" 3) "b" 4) "2"HyperLogLog
Redis HyperLogLog 是用來做基數統計的算法。
什么是基數?
比如數據集{1,3,5,10,12},那么這個數據集的基數集為{1,3,5,10,12},基數(不重復元素)為5;基數估計就是在誤差可接受的范圍內,快速計算基數。
優點:在輸入元素的數量或者體積非常大時,計算基數所需空間總是固定的,并且是很小的。
使用場景 :統計每天訪問IP數,統計頁面實時UV,統計在線用戶數,統計用戶每天搜索不同詞條的個數…
pfadd添加指定元素到HyperLogLog中
語法:pfadd key value
127.0.0.1:6379> PFADD w3c "redis" (integer) 1 127.0.0.1:6379> PFAdd w3c mongodb (integer) 1 127.0.0.1:6379> pfcount w3c (integer) 2pfcount返回給定的HyperLogLog中的基數估算值
語法:pfcount key
127.0.0.1:6379> PFAdd php thinkphp (integer) 1 127.0.0.1:6379> pfadd php laravel (integer) 1 127.0.0.1:6379> pfadd php yii2 (integer) 1 127.0.0.1:6379> pfadd php symfony (integer) 1 127.0.0.1:6379> pfcount php (integer) 4pfmerge 將多個HyperLogLog合并為一個HyperLogLog
語法:pfmerge key1 kye2
127.0.0.1:6379> pfmerge php w3c OK 127.0.0.1:6379> pfcount php (integer) 7 127.0.0.1:6379> pfcount w3c (integer) 3事務
Redis中事務(transaction)是一組命令的集合。事務和命令都是Redis的最小執行單位。
事務執行流程:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iMTlAhhZ-1640782523490)(自如初博客redis學習.assets/redis事務執行過程.png)]
事務經歷的三個階段: 1)開始事務 2)命令入列 3)執行事務
應用場景:樂觀鎖
multi 開啟一個事務
exec 執行一個事務
127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set city shanghai QUEUED 127.0.0.1:6379(TX)> exec 1) OK#語法錯誤: 執行exec將直接返回錯誤 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set city aa QUEUED 127.0.0.1:6379(TX)> set cit (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379(TX)> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get city "shanghai"#運行錯誤:除了錯誤的命令,其他命令都會被執行 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set name test QUEUED 127.0.0.1:6379(TX)> sadd name php QUEUED 127.0.0.1:6379(TX)> set name mysql QUEUED 127.0.0.1:6379(TX)> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) OK 127.0.0.1:6379> get name "mysql"discard 取消事務
127.0.0.1:6379> get name "mysql" 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set name oracle QUEUED 127.0.0.1:6379(TX)> discard OK 127.0.0.1:6379> get name "mysql"**watch 監聽一個或者多個key(決定事務是執行還是回滾) **
#一個命令行窗口 127.0.0.1:6379> get name "mysql" 127.0.0.1:6379> watch name OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set name mysqli QUEUED 127.0.0.1:6379(TX)> exec 1) OK 127.0.0.1:6379> get name "mysqli"#窗口1 127.0.0.1:6379> get name "mysqli" 127.0.0.1:6379> watch name OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set name oracle QUEUED #暫停,重新打開一個窗口,輸入窗口2的命令,然后再繼續輸入以下命令 127.0.0.1:6379(TX)> exec (nil) 127.0.0.1:6379> get name "pdo"#窗口2 127.0.0.1:6379> set name pdo OK- 可以監聽一個或多個鍵,一旦其中有一個鍵被修改或者刪除,之后的事務 將不執行
unwatch 取消watch命令對所有key的監聽
127.0.0.1:6379> unwatch OKRedis發布訂閱
Redis發布訂閱(pub/sub)是一種消息通信模式:發送者發送消息,訂閱者接受消息
Redis客戶端可以訂閱任意數量的頻道
subscribe 訂閱一個或者多個頻道
語法:subscribe channel
#窗口1 127.0.0.1:6379> subscribe redisChat Reading messages... (press Ctrl-C to quit) #別關,下面發送指定信息到這個channelpublish將信息發送到指定的頻道
語法:publish channel message
#窗口2 127.0.0.1:6379> publish redisChat "redis is a caching technique" (integer) 1#窗口1(自動出現) Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1 1) "message" 2) "redisChat" 3) "redis is a caching technique"- 該消息返回接受這條消息的訂閱者數量
pubsub查看訂閱和發布系統狀態
127.0.0.1:6379> pubsub channels 1) "redisChat"unscbscribe 退訂給定一個或者多個頻道的信息
127.0.0.1:6379> unsubscribe redisChat 1) "unsubscribe" 2) "redisChat" 3) (integer) 0psubscribe 訂閱一個或多個符合給定模式的頻道
127.0.0.1:6379> psubscribe cctv?*
Reading messages… (press Ctrl-C to quit)
“psubscribe”
“cctv?*”
(integer) 1
“pmessage”
“cctv?*”
“cctv1”
“\xe6\x96\xb0\xe9\x97\xbb”
punsubscribe退訂給定的模式的頻道
127.0.0.1:6379> punsubscribe cctv?* 1) "punsubscribe" 2) "cctv?*" 3) (integer) 0Redis兩種持久化方式
Redis持久化是將存儲在內存中的數據永久的保存在磁盤中。
Redis為什么需要持久化?
Redis的強大性能很大程度上是因為將所有的數據都存儲在內存當中,當Redis重啟后,所有內存中的數據都會丟失。
Redis支持RDB和AOF兩種持久化方式:
RDB是 根據指定的規則定時的將內存中的數據存儲到硬盤中;
AOF是 在每次執行命令之后將命令本身記錄下來
兩種持久化方式可以單獨使用其中一種,更多的是將兩種結合使用。
RDB方式實現持久化
RBD方式的持久化是通過快照(snapshotting)完成的,當符合一定條件時Redis會自動將內存中的所有數據生成一份副本并存儲在硬盤上,這個過程就是快照。
以下幾種情況時,redis會對數據進行快照:
- 根據配置規則進行自動快照
- 用戶執行save或者bgsave命令
- 執行FLUSHALL命令
- 執行復制(replication)時
(1)根據配置規則就行自動快照
#900秒后,有一個或者一個以上的鍵被修改,則 進行快照 save 900 1 #300秒后,至少有10個鍵被修改,則進行快照 save 300 10 #60秒內,至少有10000鍵被修改,則進行快照 save 60 10000- 如上可以看到:每條快照以save開頭,且每條快照條件獨占一行。可以同時存在多個條件,條件之間是“或”關系。
根據配置規則進行自動快照
實現:
步驟1 )注釋默認的配置文件并設置新的快照
#save 900 1 #save 300 10 #save 60 10000 save 60 3步驟2) 刪除dump.rdb文件
步驟3) 設置值,并等待60s后查看是否有dump文件的生成
127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> set k2 v2 OK 127.0.0.1:6379> set k3 v3 OK 127.0.0.1:6379> set k4 v4 OK 127.0.0.1:6379> set k5 v5 OK步驟4)60秒已經生成dump文件,重啟虛擬機,強制退出redis,假設突然斷電
步驟5)重啟redis,查看數據是否恢復
127.0.0.1:6379> get k1 "v1"可以看到 數據已經恢復了,這就是自動執行快照。
用戶執行save或者bgsave命令
除了自動快照之外,還可以進行手動快照。當服務重啟,手動遷移以及備份時,可以使用手動進行快照操作。
save命令
當執行save指令時,redis同步進行快照操作,在快照執行的過程中會阻塞所有來自客戶端的請求。當數據過多時,save會導致Redis長時間不響應。
127.0.0.1:6379> set k8 v8 OK 127.0.0.1:6379> save OK恢復數據:只需將備份文件(dump.rdb)移動到redis安裝目錄并啟動服務即可。
#獲取redis目錄命令 127.0.0.1:6379> config get dir 1) "dir" 2) "/www/server/redis"bgsave命令
手動執行快照,推薦使用bgsave。bgsave命令可以在后臺異步進行快照操作,快照的同時服務可以繼續響應來自客戶端的請求。執行bgsave后,redis會立即返回OK,表示開始執行快照操作。通過lastsave命令查看最近一次成功執行快照的時間。
127.0.0.1:6379> set k9 v9 OK 127.0.0.1:6379> bgsave Background saving started 127.0.0.1:6379> lastsave (integer) 1640742064flushall命令
當執行flushall命令時,Redis清除Redis服務器中的所有數據。無論清空服務器的過程中是否觸發了自動快照條件,只要自動快照條件不為空,Redis就會執行一次快照操作。
執行復制時
當設置了主從模式,Redis會在復制初始化時進行自動快照。
快照原理Redis默認會將快照文件存儲在Redis當前進程的工作目錄中的dump.rdb文件中。通過配置dir和dbfilename兩個參數分別指定快照文件的存儲路徑和文件名。
快照執行過程如下:
1)Redis使用fork函數復制一份當前進程(父進程)的副本(子進程)
2)父進程繼續接收并處理客戶端發來的命令,而子進程開始講內存中的數據寫入硬盤的臨時文件
3)當子進程寫入萬所有數據后會用該臨時文件替換舊的RDB文件,至此一次快照操作完成。
方式二:AOF方式實現
當使用Redis存儲非臨時數據時,一般需要打開AOF持久化來降低進程中職導致的數據丟失。
實現
步驟1):開啟AOF
Redis默認不開啟AOF(append only file)方式持久化,通過修改配置文件參數啟動
appendonly yesappendfsync always步驟2):寫入命令
127.0.0.1:6379> set name wangwu OK步驟3)查看appendonly.aof文件
[root@dcdfa0e9eb71 redis]# ll appendonly.aof -rwxr-xr-x 1 redis redis 0 Dec 29 10:04 appendonly.aof這樣aof就實現了。
AOF重寫
為什么需要重寫?有些命令是冗余的,也會被記錄。隨著命令不斷寫入,AOF文件越來越大,這時希望對該文件進行優化,針對冗余命令,可以進行刪除,保留一條。
手動后臺重寫bgrewriteaof
#窗口1 127.0.0.1:6379> bgrewriteaof Background append only file rewriting started #窗口2 [root@dcdfa0e9eb71 redis]# ll appendonly.aof -rwxr-xr-x 1 redis redis 148 Dec 29 10:15 appendonly.aof #暫停,再窗口1輸入berewriteaof的redis命令后 [root@dcdfa0e9eb71 redis]# ll appendonly.aof -rwxr-xr-x 1 redis redis 112 Dec 29 10:15 appendonly.aof可以清楚的看到,aof文件變小了
自動重寫
#redis.conf默認配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb重寫的作用
1)降低磁盤占用量,提高自盤利用率
2)提高持久化效率,降低持久化時間,提高I/O性能
3)降低數據恢復用時,提高數據恢復效率
同步硬盤數據
雖然每次執行命令,aof都會將命令記錄在aof文件中,而實際上,由于操作系統緩存機制,數據并沒有真正寫入磁盤,而是進入了系統的硬盤緩存。默認情況下系統每30秒會執行一次同步操作,這時才是真正寫入磁盤。
如果這30秒的過程中國,系統異常退出,則會導致硬盤緩存中的數據丟失,這時aof持久化無法容忍的損失。可以通過appendsync參數設置同步時機:
appendsync always #表示每次執行寫入都會執行同步 appendsync no #表示不主動進行同步操作 appendsync everysec #表示每秒進行同步Redis中從復制之一主多從
主從復制時指將一條主節點(master)Redis服務器的數據復制到其他的從節點(slave)Redus服務器。朱勇之間的復制時單向的,只能是由主節點到從節點。
一個主數據庫可以擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫
作用:數據冗余,故障恢復,負載均衡,讀寫分離,高可用基石(實現哨兵和集群的基礎)
Redis可以通過slaveof與配置文件兩種方式實現主從復制,推薦使用配置文件方式。
方式一 通過saveof命令行方式實現主從復制
實現一主兩從
1)直接啟動redis服務;不帶任何參數,默認監聽6379端口,將此作為主服務
#啟動主服務 [root@dcdfa0e9eb71 bin]# /www/server/redis/src/redis-server 57811:C 29 Dec 2021 10:34:10.057 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo clock: POSIX clock_gettime2)客戶端連接6379端口的Redis主服務器
#查看配置信息 127.0.0.1:6379> info replication # Replication role:master #master主數據庫 connected_slaves:0 master_failover_state:no-failover master_replid:26d969624f32fcdb591ca1b65639b53d7df769b6 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> set name master OK3)使用6380端口開啟Redis從服務器
需要重新打開窗口進行服務器配置
[root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-server --port 6380 --slaveof 127.0.0.1 6379連接成功后,主Redis服務器數據庫的任何數據變化通過自動同步到從Redis庫(6380)中。
4)客戶端連接6380 Redis服務器
需要重新打開窗口進行連接
[root@dcdfa0e9eb71 /]# redis-cli -p 6380查看主從信息
127.0.0.1:6380> info replication # Replication role:slave #6380為從庫 master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_read_repl_offset:70 slave_repl_offset:70 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:83f3e0a67b4f509ada3e0a0cb0ec3a12209142c7 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:70 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:705)使用6381端口啟動服務
6379@dcdfa0e9eb71 /]# /www/server/redis/src/redis-server --port 6381 --slaveof 127.0.0.1查看配置信息
[root@dcdfa0e9eb71 /]# redis-cli -p 6381 127.0.0.1:6381> INFO replication # Replication role:slave #6381為從庫 master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:5 master_sync_in_progress:0 slave_read_repl_offset:238 slave_repl_offset:238 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:83f3e0a67b4f509ada3e0a0cb0ec3a12209142c7 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:238 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2387)實測
#主庫 6379 127.0.0.1:6379> set name master OK #從庫 6380 127.0.0.1:6380> get name (nil) 127.0.0.1:6380> get name "master" #從庫 6381 127.0.0.1:6381> get name (nil) 127.0.0.1:6381> get name "master"方式二 通過conf配置文件實現主從復制
實現一主兩從
1)創建6380和6381配置文件,由于這兩個配置文件只需要修改一下端口,因此只列出一個配置文件來
cp redis.conf redis6380.conf vim /www/server/redis /redis_6380.conf############################# ### 以下配置是6380的配置 ############################# # 端口 port 6380# 后臺啟動 daemonize yespidfile /www/server/redis /redis_6380.pidloglevel notice# 日志文件 logfile "/www/server/redis /redis_6380.log"# 快照文件 dbfilename 6380_dump.rdbdir /www/server/redis /6380replicaof 127.0.1 6379 replica-read-only yes2)啟動redis主服務
[root@dcdfa0e9eb71 bin]# /www/server/redis/src/redis-server3)客戶端登陸主服務器并查看主從信息
[root@dcdfa0e9eb71 /]# redis-cli -p 6380 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_read_repl_offset:70 slave_repl_offset:70 slave_priority:100 ...4)啟動6380端口的Redis服務器
- 創建6380 ,6381目錄。不然會啟動失敗
6379客戶端查看鏈接信息
[root@dcdfa0e9eb71 /]# redis-cli -p 6379 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:2350fbf04aebef085c7def0684a7b8f052f13283 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=1 master_failover_state:no-failover master_replid:66026b04b66fe9cadf2c0e995afd85b09d5f0d88 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:14 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:14可以看到有一個已經連接了
7)測試
#6379 主 127.0.0.1:6379> set age 18 OK #6380 從 127.0.0.1:6380> get age "18"主從復制原理
1)當啟動一個從數據庫后,從數據庫會向主數據庫發送SYNC命令
2)主數據庫接收到SYNC命令后開始在后臺保存快照(RDB持久化過程),并將保存快照期間接收的命令緩存起來。快照完成后,Redis會將快照文件和所有緩存的命令發送給從數據庫
3)從數據庫收到后,會載入快照文件并執行到緩存的命令
以上過程是?復制的初始化。? 復制初始化結束后,主數據庫每當接收到寫命令時就會將命令同步給從數據庫,從而保證主從數據庫一致。
讀寫分離一致性
通過復制可以實現讀寫分離,可以提高服務器的負載能力。讀頻率大于寫頻率的應用場景中,當單機Redis無法應付大量的讀請求時,可以通過復制功能建立多個從數據庫節點,主數據庫只進行寫操作,而從數據庫負責讀操作。
從數據庫持久化
持久化是比較耗時的操作,為了提高性能,可以通過復制功能建立一個或者多個 數據庫,并在從數據庫中開啟持久化。同時主數據庫中禁用持久化。當從數據庫崩潰重啟后主數據庫會自動將數據同步過來,因此不用擔心數據丟失
如果主數據庫崩潰時,情況就變得復雜很多。嚴格按照以下步驟
1)在從數據庫中使用replicaof no one 命令將從數據庫提升成主數據庫繼續服務
2)啟動之崩潰的主數據庫,然后使用replicaof命令將其設置成新的主數據庫的從數據庫,即可將數據同步回來。
無硬盤復制
主從復制時基于RDB方式的持久化實現的,主數據庫端在后臺保存RDB快照,從數據庫端則接受并載入快照文件。
增量復制
當主數據庫連接斷開后,從數據庫會發送SYNC命令重新進行一次完整復制操作。這樣即使斷開期間數據庫變化很小,也需要將數據庫中的所有數據重新快照并傳送一次。
增量復制基于以下三點實現:
1)從數據庫會存儲主數據庫運行ID(run id)。每個Redis運行實例都會擁有一個唯一的運行ID,每當實例重啟就會自動生成一個新的運行ID
2)在復制同步階段,主數據庫每將一個命令傳送給從數據庫時,都會同時把該命令存放到一個積壓隊列(backlog)中,并記錄下當前積壓隊列中存放的命令的偏移量范圍
3)從數據庫接收到主數據庫傳來的命令時,會記錄下該命令的偏移量
這三點是實現增量復制的基礎。當主從連接準備就緒后,從數據庫會發送一條PSYNC命令來告訴主數據庫可以把所有的數據同步過來 。
格式為PSYNC 主數據庫的運行ID 斷開前最新的命令偏移量
步驟:
①首先,主數據庫會判斷從數據庫傳送來的運行ID是否和自己運行的ID相同。此步驟是為了確保從數據庫之前確實是和自己同步的,以免從數據庫拿到錯誤的數據
②其次判斷從數據庫最后同步成功的命令偏移量是否在積壓隊列中,如果在則可以執行增量復制,并將積壓隊列中相應的命令發送給從數據庫
積壓隊列本質上是一個固定長度的循環隊列默認情況下積壓隊列的大小為1MB,可以通過配置文件repl-backlog-size選項來調整。積壓隊列越大,允許的主從數據庫斷線的時間就越長。
Redis哨兵模式配置的實現
Redis哨兵模式是基于主從復制的。
當數據庫宕機之后,哨兵會推選出一個新的主服務器,并把之前的主服務器變成新的從服務器。這一過程是哨兵自動完成,不需要人工參與。
什么是哨兵
哨兵是一個獨立的進程。其原理是哨兵通過發送命令,等待redis服務器響應,從而監控運行的多個redis實例
哨兵的作用
*可以使用一個哨兵,也可以使用多個哨兵進行監控,實際使用環境中使用多個哨兵(建議奇數)進行監控
實現步驟
1)配置并開啟主從復制(上面已經實現,直接使用)
[root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server /www/server/redis/redis.conf [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server /www/server/redis/redis6380.conf [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server /www/server/redis/redis6381.conf [root@dcdfa0e9eb71 redis]# redis-cli -p 6379 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=70,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=70,lag=1 master_failover_state:no-failover master_replid:517ffcafa445b9cc6acc2b4a7ee5700773746bbf master_replid2:0000000000000000000000000000000000000000 master_repl_offset:70 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:702)使用配置文件配置哨兵
①準備工作
# 切換到redis目錄 [root@192 redis]# cd /www/server/redis/# 創建配置文件哨兵目錄 [root@192 redis]# mkdir /www/server/redis/redis_sentinel_conf # 復制默認的哨兵文件到目錄 [root@192 redis]# cp ./sentinel.conf /www/server/redis//redis_sentinel_conf/sentinel_6379.conf [root@192 redis]# cd /usr/local/bin/redis_sentinel_conf/② 編輯哨兵配置文件
[root@192 redis]# cd /usr/local/bin/redis_sentinel_conf/ [root@192 redis_sentinel_conf]# vim sentinel_6379.conf修改內容為:
# 端口 port 26379# 是否守護進程啟動 daemonize no# 工作目錄 dir /tmp# 聲明該哨兵的主庫是mymaster,主庫的ip和端口分別是127.0.0.1 和 6379 # 最后一個2的含義是:當哨兵發生領導選舉時,需要2個哨兵通過才行 sentinel monitor mymaster 127.0.0.1 6379 2# 在mymaster宕機30秒后進行主觀下線 sentinel down-after-milliseconds mymaster 30000# 指定在發生failover故障轉移時最多可以有1個slave同時對新的master進行同步 sentinel parallel-syncs mymaster 1# 設置故障轉移超時時間為180秒 sentinel failover-timeout mymaster 180000③復制sentinel_6379.conf為sentinel_6380.conf,sentinel_6381.conf并修改對應的端口為26380,26381
[root@192 redis_sentinel_conf]# cp sentinel_6379.conf ./sentinel_6380.conf [root@192 redis_sentinel_conf]# cp sentinel_6379.conf ./sentinel_6381.conf3)啟動配置好的三個哨兵服務
①啟動26379服務并連接
[root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6379.conf客戶端使用26379端口連接哨兵服務器
[root@dcdfa0e9eb71 redis]# redis-cli -p 26379 可以使用info查看哨兵顯示的信息 127.0.0.1:26379> info # Server redis_version:6.2.6 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:36599a7c3e389a76 redis_mode:sentinel os:Linux 5.10.47-linuxkit x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:c11-builtin gcc_version:8.4.1 process_id:73653 process_supervised:no run_id:82fa9039e9928d9809429365592ef2f732e2a94d tcp_port:26379 ...... # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:379,slaves=2,sentinels=2可以看到配置文件自動發生改變
②啟動26380哨兵服務
[root@dcdfa0e9eb71 redis_sentinel_conf]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6380.conf查看26379服務,已近多了幾個配置
73653:X 29 Dec 2021 14:29:03.124 # Sentinel ID is a4fe46846ee24ff8a183c949ff813aa620d8ef90
73653:X 29 Dec 2021 14:29:03.125 # +monitor master mymaster 127.0.0.1 6379 quorum 2
73653:X 29 Dec 2021 14:29:03.126 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
73653:X 29 Dec 2021 14:29:03.180 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
73653:X 29 Dec 2021 14:41:22.742 * +sentinel sentinel 0b968d92eeb26074330ab631221c1ace39be42fe 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
73653:X 29 Dec 2021 14:43:29.244 * +sentinel sentinel bd67baf85fcc6a7664336bb06e725b9321082bac 127.0.0.1 26381 @ mymaster 127.0.0.1 6379
③啟動26381哨兵服務
[root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6381.conf 74632:X 29 Dec 2021 14:43:27.178 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 74632:X 29 Dec 2021 14:43:27.179 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=74632, just started 74632:X 29 Dec 2021 14:43:27.179 # Configuration loaded 74632:X 29 Dec 2021 14:43:27.180 * monotonic clock: POSIX clock_gettime_.__.-``__ ''-.__.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit.-`` .-```. ```\/ _.,_ ''-._( ' , .-` | `, ) Running in sentinel mode|`-._`-...-` __...-.``-._|'` _.-'| Port: 26381| `-._ `._ / _.-' | PID: 74632`-._ `-._ `-./ _.-' _.-'|`-._`-._ `-.__.-' _.-'_.-'|| `-._`-._ _.-'_.-' | https://redis.io`-._ `-._`-.__.-'_.-' _.-'|`-._`-._ `-.__.-' _.-'_.-'|| `-._`-._ _.-'_.-' |`-._ `-._`-.__.-'_.-' _.-'`-._ `-.__.-' _.-'`-._ _.-'`-.__.-'74632:X 29 Dec 2021 14:43:27.206 # Sentinel ID is bd67baf85fcc6a7664336bb06e725b9321082bac 74632:X 29 Dec 2021 14:43:27.206 # +monitor master mymaster 127.0.0.1 6379 quorum 2 74632:X 29 Dec 2021 14:43:27.208 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:27.228 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:28.993 * +sentinel sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:29.032 * +sentinel sentinel 0b968d92eeb26074330ab631221c1ace39be42fe 127.0.0.1 26380 @ mymaster 127.0.0.1 63794)實戰測試
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨
①6379主服務器中寫入一條數據
127.0.0.1:6379> set ziruchu hello OK②6380、6381從服務器中讀取
127.0.0.1:6380> get ziruchu "hello" 127.0.0.1:6381> get ziruchu "hello"③ 宕機6379主服務器
由于6379主服務并沒有使用守護進程啟動,因此直接使用Ctrl+c斷開服務或者使用ps -aux查看6379服務的進程號然后kill -9 進程號 模擬宕機
④查看隨意一個哨兵
[root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6381.conf 74632:X 29 Dec 2021 14:43:27.178 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 74632:X 29 Dec 2021 14:43:27.179 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=74632, just started 74632:X 29 Dec 2021 14:43:27.179 # Configuration loaded 74632:X 29 Dec 2021 14:43:27.180 * monotonic clock: POSIX clock_gettime _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26381 | `-._ `._ / _.-' | PID: 74632 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-'74632:X 29 Dec 2021 14:43:27.206 # Sentinel ID is bd67baf85fcc6a7664336bb06e725b9321082bac 74632:X 29 Dec 2021 14:43:27.206 # +monitor master mymaster 127.0.0.1 6379 quorum 2 74632:X 29 Dec 2021 14:43:27.208 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:27.228 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:28.993 * +sentinel sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:29.032 * +sentinel sentinel 0b968d92eeb26074330ab631221c1ace39be42fe 127.0.0.1 26380 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.518 # +sdown master mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.581 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2 74632:X 29 Dec 2021 15:18:10.581 # +new-epoch 1 74632:X 29 Dec 2021 15:18:10.581 # +try-failover master mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.613 # +vote-for-leader bd67baf85fcc6a7664336bb06e725b9321082bac 1 74632:X 29 Dec 2021 15:18:10.613 # a4fe46846ee24ff8a183c949ff813aa620d8ef90 voted for a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 74632:X 29 Dec 2021 15:18:10.650 # 0b968d92eeb26074330ab631221c1ace39be42fe voted for a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 74632:X 29 Dec 2021 15:18:10.859 # +config-update-from sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.859 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:40.861 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:21:53.454 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381可以看到6381被選為主服務器
⑤6381服務器中設置一個值,然后從服務器中查看
#主服務器6381 [root@dcdfa0e9eb71 /]# redis-cli -p 6381 127.0.0.1:6381> info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=493296,lag=0 master_failover_state:no-failover master_replid:4648e7de667cfee4e37c14b9a08c605f05e56681 master_replid2:517ffcafa445b9cc6acc2b4a7ee5700773746bbf master_repl_offset:493296 second_repl_offset:470776 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:43 repl_backlog_histlen:493254 127.0.0.1:6381> set name 6381 OK#從服務器6380 [root@dcdfa0e9eb71 redis]# redis-cli -p 6380 127.0.0.1:6380> get name "a" 127.0.0.1:6380> get name "b" 127.0.0.1:6380> get name Error: Server closed the connection 127.0.0.1:6380> get name "6381" 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6381 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_read_repl_offset:499356 slave_repl_offset:499356 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:4648e7de667cfee4e37c14b9a08c605f05e56681 master_replid2:517ffcafa445b9cc6acc2b4a7ee5700773746bbf master_repl_offset:499356 second_repl_offset:470776 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:499356⑥重新啟動6379服務并用客戶端連接
[root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server 77182:C 29 Dec 2021 15:21:53.079 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 77182:C 29 Dec 2021 15:21:53.079 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=77182, just started 77182:C 29 Dec 2021 15:21:53.079 # Warning: no config file specified, using the default config. In order to specify a config file use /www/server/redis/src/redis-server /path/to/redis.conf 77182:M 29 Dec 2021 15:21:53.081 * monotonic clock: POSIX clock_gettime _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 77182 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 77182:M 29 Dec 2021 15:21:53.082 # Server initialized 77182:M 29 Dec 2021 15:21:53.092 * Loading RDB produced by version 6.2.6 77182:M 29 Dec 2021 15:21:53.092 * RDB age 3404 seconds 77182:M 29 Dec 2021 15:21:53.092 * RDB memory usage when created 1.85 Mb 77182:M 29 Dec 2021 15:21:53.092 # Done loading RDB, keys loaded: 2, keys expired: 0. 77182:M 29 Dec 2021 15:21:53.092 * DB loaded from disk: 0.007 seconds 77182:M 29 Dec 2021 15:21:53.092 * Ready to accept connections 77182:S 29 Dec 2021 15:22:03.410 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer. 77182:S 29 Dec 2021 15:22:03.410 * Connecting to MASTER 127.0.0.1:6381 77182:S 29 Dec 2021 15:22:03.410 * MASTER <-> REPLICA sync started 77182:S 29 Dec 2021 15:22:03.411 * REPLICAOF 127.0.0.1:6381 enabled (user request from 'id=5 addr=127.0.0.1:34810 laddr=127.0.0.1:6379 fd=10 name=sentinel-0b968d92-cmd age=10 idle=0 flags=x db=0 sub=0 psub=0 multi=4 qbuf=196 qbuf-free=40758 argv-mem=4 obl=45 oll=0 omem=0 tot-mem=61468 events=r cmd=exec user=default redir=-1') 77182:S 29 Dec 2021 15:22:03.411 * Non blocking connect for SYNC fired the event. 77182:S 29 Dec 2021 15:22:03.412 * Master replied to PING, replication can continue... 77182:S 29 Dec 2021 15:22:03.412 * Trying a partial resynchronization (request e662599320845936adbf62088ab352d6137febea:1). 77182:S 29 Dec 2021 15:22:03.490 * Full resync from master: 4648e7de667cfee4e37c14b9a08c605f05e56681:516772 77182:S 29 Dec 2021 15:22:03.490 * Discarding previously cached master state. 77182:S 29 Dec 2021 15:22:03.604 * MASTER <-> REPLICA sync: receiving 199 bytes from master to disk 77182:S 29 Dec 2021 15:22:03.611 * MASTER <-> REPLICA sync: Flushing old data 77182:S 29 Dec 2021 15:22:03.611 * MASTER <-> REPLICA sync: Loading DB in memory 77182:S 29 Dec 2021 15:22:03.678 * Loading RDB produced by version 6.2.6 77182:S 29 Dec 2021 15:22:03.678 * RDB age 0 seconds 77182:S 29 Dec 2021 15:22:03.678 * RDB memory usage when created 2.03 Mb 77182:S 29 Dec 2021 15:22:03.678 # Done loading RDB, keys loaded: 2, keys expired: 0. 77182:S 29 Dec 2021 15:22:03.678 * MASTER <-> REPLICA sync: Finished with success⑦6379客戶端查看
[root@dcdfa0e9eb71 /]# redis-cli -p 6379 127.0.0.1:6379> info replication # Replication role:slave master_host:127.0.0.1 master_port:6381 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_read_repl_offset:525629 slave_repl_offset:525629 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:4648e7de667cfee4e37c14b9a08c605f05e56681 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:525629 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:516773 repl_backlog_histlen:8857 127.0.0.1:6379> get name "6381"到這里,哨兵配置完成。
下面為補充信息-哨兵啟動信息
6381哨兵顯示信息 [root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6381.conf 74632:X 29 Dec 2021 14:43:27.178 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 74632:X 29 Dec 2021 14:43:27.179 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=74632, just started 74632:X 29 Dec 2021 14:43:27.179 # Configuration loaded 74632:X 29 Dec 2021 14:43:27.180 * monotonic clock: POSIX clock_gettime _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26381 | `-._ `._ / _.-' | PID: 74632 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 74632:X 29 Dec 2021 14:43:27.206 # Sentinel ID is bd67baf85fcc6a7664336bb06e725b9321082bac 74632:X 29 Dec 2021 14:43:27.206 # +monitor master mymaster 127.0.0.1 6379 quorum 2 74632:X 29 Dec 2021 14:43:27.208 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:27.228 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:28.993 * +sentinel sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 14:43:29.032 * +sentinel sentinel 0b968d92eeb26074330ab631221c1ace39be42fe 127.0.0.1 26380 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.518 # +sdown master mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.581 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2 74632:X 29 Dec 2021 15:18:10.581 # +new-epoch 1 74632:X 29 Dec 2021 15:18:10.581 # +try-failover master mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.613 # +vote-for-leader bd67baf85fcc6a7664336bb06e725b9321082bac 1 74632:X 29 Dec 2021 15:18:10.613 # a4fe46846ee24ff8a183c949ff813aa620d8ef90 voted for a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 74632:X 29 Dec 2021 15:18:10.650 # 0b968d92eeb26074330ab631221c1ace39be42fe voted for a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 74632:X 29 Dec 2021 15:18:10.859 # +config-update-from sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74632:X 29 Dec 2021 15:18:10.859 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:18:40.861 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74632:X 29 Dec 2021 15:21:53.454 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 6380哨兵顯示信息[root@dcdfa0e9eb71 redis_sentinel_conf]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6380.conf 74461:X 29 Dec 2021 14:41:20.739 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 74461:X 29 Dec 2021 14:41:20.739 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=74461, just started 74461:X 29 Dec 2021 14:41:20.739 # Configuration loaded 74461:X 29 Dec 2021 14:41:20.742 * monotonic clock: POSIX clock_gettime _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26380 | `-._ `._ / _.-' | PID: 74461 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 74461:X 29 Dec 2021 14:41:20.762 # Sentinel ID is 0b968d92eeb26074330ab631221c1ace39be42fe 74461:X 29 Dec 2021 14:41:20.762 # +monitor master mymaster 127.0.0.1 6379 quorum 2 74461:X 29 Dec 2021 14:41:20.766 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 14:41:20.785 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 14:41:22.600 * +sentinel sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 14:43:29.244 * +sentinel sentinel bd67baf85fcc6a7664336bb06e725b9321082bac 127.0.0.1 26381 @ mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 15:18:10.496 # +sdown master mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 15:18:10.627 # +new-epoch 1 74461:X 29 Dec 2021 15:18:10.649 # +vote-for-leader a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 74461:X 29 Dec 2021 15:18:10.858 # +config-update-from sentinel a4fe46846ee24ff8a183c949ff813aa620d8ef90 127.0.0.1 26379 @ mymaster 127.0.0.1 6379 74461:X 29 Dec 2021 15:18:10.859 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 74461:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 74461:X 29 Dec 2021 15:18:10.859 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74461:X 29 Dec 2021 15:18:40.889 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74461:X 29 Dec 2021 15:21:53.460 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 74461:X 29 Dec 2021 15:22:03.410 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 6379哨兵顯示信息 [root@dcdfa0e9eb71 /]# /www/server/redis/src/redis-sentinel /www/server/redis/redis_sentinel_conf/sentinel_6379.conf 73653:X 29 Dec 2021 14:29:03.047 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 73653:X 29 Dec 2021 14:29:03.052 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=73653, just started 73653:X 29 Dec 2021 14:29:03.055 # Configuration loaded 73653:X 29 Dec 2021 14:29:03.056 * monotonic clock: POSIX clock_gettime _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.6 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26379 | `-._ `._ / _.-' | PID: 73653 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 73653:X 29 Dec 2021 14:29:03.124 # Sentinel ID is a4fe46846ee24ff8a183c949ff813aa620d8ef90 73653:X 29 Dec 2021 14:29:03.125 # +monitor master mymaster 127.0.0.1 6379 quorum 2 73653:X 29 Dec 2021 14:29:03.126 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 14:29:03.180 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 14:41:22.742 * +sentinel sentinel 0b968d92eeb26074330ab631221c1ace39be42fe 127.0.0.1 26380 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 14:43:29.244 * +sentinel sentinel bd67baf85fcc6a7664336bb06e725b9321082bac 127.0.0.1 26381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.514 # +sdown master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.573 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2 73653:X 29 Dec 2021 15:18:10.573 # +new-epoch 1 73653:X 29 Dec 2021 15:18:10.573 # +try-failover master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.601 # +vote-for-leader a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 73653:X 29 Dec 2021 15:18:10.613 # bd67baf85fcc6a7664336bb06e725b9321082bac voted for bd67baf85fcc6a7664336bb06e725b9321082bac 1 73653:X 29 Dec 2021 15:18:10.650 # 0b968d92eeb26074330ab631221c1ace39be42fe voted for a4fe46846ee24ff8a183c949ff813aa620d8ef90 1 73653:X 29 Dec 2021 15:18:10.657 # +elected-leader master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.657 # +failover-state-select-slave master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.715 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.715 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.792 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.847 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.847 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:10.855 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:11.805 # -odown master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:11.806 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:11.806 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:11.882 # +failover-end master mymaster 127.0.0.1 6379 73653:X 29 Dec 2021 15:18:11.882 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 73653:X 29 Dec 2021 15:18:11.882 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 73653:X 29 Dec 2021 15:18:11.882 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 73653:X 29 Dec 2021 15:18:41.891 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381啟動信息解釋
+slave 表示發現了新的從數據庫;
+sdown 表示哨兵主觀認為主數據庫停止了服務
_odown 表示哨兵客觀認為主數據庫停止了服務
+try-failover 表示哨兵開始進行故障恢復
+failover-end 表示哨兵完成故障恢復,期間涉及的內容比較復雜,包括領頭哨兵的選舉、備選數據庫的選擇等
+switch-master 表示主數據庫人6379端口切換到6381端口,即6381升級為主數據庫
舉個栗子:當6380宕機后,推選出6381作為主數據庫,此時6379還是宕機狀態,當6379恢復之后,會轉變為6381端口實例的從數據庫來運行,因此,哨兵將6379的實例信息修改為了6381的從數據庫。
哨兵實現原理:
一個哨兵進程啟動之后會讀取配置文件的內容,通過# sentinel monitor <master-name> <ip> <redis-port> <quorum>找出需要監控的主數據庫
例如:sentinel_6379.conf中 sentinel monitor mymaster 127.0.0.1 6381 2
一個redis哨兵節點可以同時監控多個Redis主從系統,其配置如下:
一個哨兵節點可以同時監控多個Redis主從系統,其配置如下:
#暫未配置 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel monitor othermaster 127.0.0.1 6380 2[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5JoBy6iA-1640782523496)(自如初博客redis學習.assets/image-20211229162243900.png)]
多個哨兵同時監控一個Redis主從系統。上一篇文章記錄的就是多個哨兵監控一個主從。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ot8vWe60-1640782523498)(自如初博客redis學習.assets/image-20211229143529043.png)]
配置含義解釋
sentinel monitor mymaster 127.0.0.1 6379 2mymaster 表示要監控的主數據庫名字。可以自定義,名字必須由小寫字母、數字和’.-_'組成
127.0.0.1 表示主數據庫地址
6379 表示主數據庫端口號
2 表示最低通過票數。如當為3哨兵時,有2個認為主數據庫掛了,那就是掛了
#sentinel.conf其他配置含義 `sentinel down-after-milliseconds mymaster 60000` 每隔一秒發送一次`ping`命令`sentinel down-after-milliseconds othermaster 10000` 每陋600毫秒發送一次`ping`命令
哨兵原理可以理解為3個步驟:監控,通知和故障轉移
監控
哨兵啟動后,會與監控的主數據庫 建立兩條連接,其中一條用來訂閱主數據的_sentinel_:hello頻道以獲取其他同樣監控該數據庫的哨兵節點信息;
哨兵也需要定期向主數據庫發送INFO等命令來獲取主數據庫本身的信息。
和主數據庫建立連接完成之后, 哨兵會 使用另外一條連接來發送命令:
- 每10s哨兵會向主數據庫和從數據庫發送info命令
- 每2s哨兵會向主數據庫和從數據庫發送sentinel:hello頻道發送自己的信息
- 每1s哨兵會向主數據庫,從數據庫和其他哨兵節點發送ping命令
詳細理解上面3步:
首先,發送info命令使得哨兵可以獲得當前數據庫相關信息(運行ID,復制等)從而實現新節點的自動發現。哨兵借助info命令來獲取所有復制該主數據庫的從庫信息;
其次,啟動后,哨兵會向主數據庫發送info命令,通過解析返回結果來得知從數據庫列表,然后對每個從數據庫建立兩條連接;
第三,哨兵會每10s定向的向已知的主從數據庫發送info命令來獲取信息更新并進行相關操作
第四,哨兵會向主從數據庫的_sentinel_:hello頻道發送信息,與同樣監控該數據的哨兵分享自己的信息;發送消息的內容為哨兵地址+哨兵端口+哨兵的運行ID+哨兵的 配置版本+主數據庫名字+主數據庫地址+主數據庫端口+主數據庫配置版本。
通知
配置完成就會進行監控,并發送ping 命令。
當超過down-after-milliseconds指定的時間后,如果被ping的數據庫或者節點沒有進行回復,哨兵認為主觀下線
主管下線表示從當前的哨兵進程來看,該節點已經下線。如果該節點為主數據庫,則哨兵進行下一步判斷是否進行故障恢復:哨兵發送sentinel is-master-down-by-add命令通知其他哨兵節點,說,我發現這個地址的主數據庫下線了,你們來看看是不是下線了,當達到指定數量的哨兵認為主數據庫下線了,那么哨兵認為是客觀下線。
故障轉移
哨兵認為主數據庫下線之后,會進行內部投票,選出一個領頭羊,故障恢復就由這個領頭羊來操作,領頭羊的選舉有如下過程:
1.發現主數據庫客觀下線的哨兵節點(A節點)向每個哨兵節點發送命令,要求對方選自己成為新的 領頭哨兵
2.如果目標哨兵節點沒有選擇其他的哨兵節點,則同意A節點為領頭羊哨兵
3.如果A節點發現有超半數且超過quorum參數值的哨兵節點同意自己成為領頭羊節點,那么A成功成為領頭羊哨兵
4.當多個節點同時參選,則會發現沒有任何哨兵節點可選。此時每個參選節點將等待一個隨機時間重新發起參選請求,進行下一輪選舉,直到成功為止
5.選出領頭羊哨兵節點之后,領頭羊開始對主數據庫進行故障恢復,內容如下:
- 5.1 所有在線的從數據庫中,選擇優先級最高的數據庫。優先級通過slave-priority來設置;
- 5.2 如果有多個優先級最高的數據庫,則復制命令偏移量越大的越有先;
- 5.3 如果條件都一樣,則選擇運行ID較小的從數據庫
選出一個從數據庫之后,領頭羊哨兵向從數據庫發送replicaof no one命令使其升級為主數據庫。而領頭羊則向其他從數據庫發送repliaof命令使其成為新主數據庫的從數據庫。
最后進行更新內部記錄,將已經停止的舊主數據庫更新成為新的主數據庫的從數據庫身份繼續服務。
redis集群
實現
1)**創建6個實例配置文件;**此處以9000.conf為例,其余5個配置文件復制9000.conf并修改端口
[root@dcdfa0e9eb71 redis]# pwd /www/server/redis [root@dcdfa0e9eb71 redis]# mkdir clusterConf [root@dcdfa0e9eb71 redis]# cp /www/server/redis/redis.conf clusterConf/9000.conf [root@dcdfa0e9eb71 clusterConf]# cp 9000.conf 9001.conf [root@dcdfa0e9eb71 clusterConf]# cp 9000.conf 9002.conf [root@dcdfa0e9eb71 clusterConf]# cp 9000.conf 9003.conf [root@dcdfa0e9eb71 clusterConf]# cp 9000.conf 9004.conf [root@dcdfa0e9eb71 clusterConf]# cp 9000.conf 9005.conf小技巧:vi替換 文本 :【;%s/源字符串/目標字符串】 例如本例 :%s/9000/9005/
-
由于是本地單臺系統操作,因此省略了綁定地址操作,真是服務器系統中帶上ip地址。
-
由于是本地環境,為了學習記錄的需要,沒有開啟后臺守護啟動,真實服務器環境中,開啟守護進程啟動。
2)啟動配置好的6臺服務器
[root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9000.conf & [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9001.conf & [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9002.conf & [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9003.conf & [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9004.conf & [root@dcdfa0e9eb71 redis]# /www/server/redis/src/redis-server ./clusterConf/9005.conf &啟動完成之后查看redis進程
[root@dcdfa0e9eb71 clusterConf]# ps -aux | grep redis root 85259 0.1 0.1 64540 5600 pts/11 Sl+ 17:21 0:00 /www/server/redis/src/redis-server 127.0.0.1:9000 [cluster] root 85305 0.1 0.1 64540 5608 pts/7 Sl+ 17:22 0:00 /www/server/redis/src/redis-server 127.0.0.1:9001 [cluster] root 85414 0.1 0.1 64540 5552 pts/2 Sl 17:23 0:00 /www/server/redis/src/redis-server 127.0.0.1:9002 [cluster] root 85429 0.2 0.1 64540 5492 pts/2 Sl 17:23 0:00 /www/server/redis/src/redis-server 127.0.0.1:9003 [cluster] root 85436 0.2 0.1 64540 5644 pts/2 Sl 17:23 0:00 /www/server/redis/src/redis-server 127.0.0.1:9004 [cluster] root 85445 0.5 0.1 64540 5536 pts/2 Sl 17:24 0:00 /www/server/redis/src/redis-server 127.0.0.1:9005 [cluster] root 85472 0.0 0.0 12136 1092 pts/2 S+ 17:24 0:00 grep --color=auto redis可見和常規的不一樣,多了一個cluster集群的標志
3)創建集群
4) 實測
1.客戶端連接9000服務器
[root@dcdfa0e9eb71 9000]# redis-cli -c -p 9000 127.0.0.1:9000> set cluster success -> Redirected to slot [14041] located at 127.0.0.1:9002 OK 127.0.0.1:9002> get cluster "success" 127.0.0.1:9002>可以看到和普通的寫入方式不一樣。這里把寫入的數據重定向到 14041這個槽中
可以看到9003從客戶端獲取數據時,數據重定向到了14041這個插槽中獲取數據
4)故障恢復
從庫宕機測試
[root@dcdfa0e9eb71 /]# redis-cli -p 9003 shutdown停止之后,其他主庫會收到信息,查看9001日志文件,如下:
#從庫9003丟失了 85305:M 29 Dec 2021 17:33:55.819 # Connection with replica 127.0.0.1:9003 lost.85305:M 29 Dec 2021 17:34:15.057 * Marking node 0071f328a2c0a6a58cfe373ce0d8c6137bf15e0c as failing (quorum reached).#重新啟動9003從庫后收到恢復信息 85305:M 29 Dec 2021 17:36:08.901 * Clear FAIL state for node 0071f328a2c0a6a58cfe373ce0d8c6137bf15e0c: replica is reachable again. 85305:M 29 Dec 2021 17:36:08.919 * Replica 127.0.0.1:9003 asks for synchronization 85305:M 29 Dec 2021 17:36:08.923 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'e67366f3da7d5999da896d02ff440b6a58d8280d', my replication IDs are 'd05670eb8e506f706cec220981513baa93ece8d3' and '0000000000000000000000000000000000000000') 85305:M 29 Dec 2021 17:36:08.927 * Starting BGSAVE for SYNC with target: disk 85305:M 29 Dec 2021 17:36:08.943 * Background saving started by pid 86375 86375:C 29 Dec 2021 17:36:08.986 * DB saved on disk 86375:C 29 Dec 2021 17:36:08.994 * RDB: 0 MB of memory used by copy-on-write 85305:M 29 Dec 2021 17:36:09.060 * Background saving terminated with success 85305:M 29 Dec 2021 17:36:09.082 * Synchronization with replica 127.0.0.1:9003 succeeded主庫宕機測試
停止主庫9000
[root@192 /]# redis-cli -p 9000 shutdown查看從庫9005日志
...... #主庫斷開 85445:S 29 Dec 2021 17:37:39.203 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:39.207 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:39.210 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:40.216 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:40.220 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:40.224 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:41.229 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:41.235 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:41.238 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:42.243 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:40.224 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:41.229 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:41.235 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:41.238 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:42.243 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:42.247 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:42.251 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:42.750 * FAIL message received from abc2fa081d403c505b5d5127d3c3af9ffaa38538 about e4256cad47611df0aa3f6a41c89d24b91c1aa89e 85445:S 29 Dec 2021 17:37:42.758 # Start of election delayed for 589 milliseconds (rank #0, offset 952). 85445:S 29 Dec 2021 17:37:42.790 # Cluster state changed: fail 85445:S 29 Dec 2021 17:37:43.284 * Connecting to MASTER 127.0.0.1:9000 85445:S 29 Dec 2021 17:37:43.287 * MASTER <-> REPLICA sync started 85445:S 29 Dec 2021 17:37:43.290 # Error condition on socket for SYNC: Connection refused 85445:S 29 Dec 2021 17:37:43.392 # Starting a failover election for epoch 7. 85445:S 29 Dec 2021 17:37:43.407 # Failover election won: I'm the new master. #升級為主庫 85445:S 29 Dec 2021 17:37:43.410 # configEpoch set to 7 after successful failover 85445:M 29 Dec 2021 17:37:43.413 * Discarding previously cached master state. 85445:M 29 Dec 2021 17:37:43.416 # Setting secondary replication ID to 7a352c533381b86b535eb666c7e9732ad531c23d, valid up to offset: 953. New replication ID is 27d71ccdd20522d54e8190f70c6bf1f64c454f92 85445:M 29 Dec 2021 17:37:43.420 # Cluster state changed: ok概念
使用集群需要將相關配置打開,這些配置建議寫在單獨的配置中
cluster-enabled 是否開啟集群
cluster-config-file 集群節點配置文件路徑(啟動后自動生成該文件)
cluster-node-timeout 超時時間
插槽分配
在一個集群中,所有鍵都會被分配給16384個插槽(slot),而每個數據庫會負責處理其中的一部分插槽。
127.0.0.1:9001> cluster nodes b8bf4748d7039934d4ba43fe558a464592958eff 127.0.0.1:9004@19004 slave f70b68962d8fb9b485cd420b1731b997feac12ad 0 1640770784000 3 connected abc2fa081d403c505b5d5127d3c3af9ffaa38538 127.0.0.1:9001@19001 myself,master - 0 1640770785000 2 connected 5461-10922 e4256cad47611df0aa3f6a41c89d24b91c1aa89e 127.0.0.1:9000@19000 master,fail - 1640770645974 1640770641000 1 disconnected 1baffc136c23418c05bda6805614fc4a29d02004 127.0.0.1:9005@19005 master - 0 1640770784709 7 connected 0-5460 0071f328a2c0a6a58cfe373ce0d8c6137bf15e0c 127.0.0.1:9003@19003 slave abc2fa081d403c505b5d5127d3c3af9ffaa38538 0 1640770782000 2 connected f70b68962d8fb9b485cd420b1731b997feac12ad 127.0.0.1:9002@19002 master - 0 1640770785716 3 connected 10923-16383可以看到,9000負責0-5460個插槽。初始化集群時分配給每個節點的插槽都是連續的 ,事實上redis對此并沒有限制,可以將任意插槽分配任意節點負責。
鍵與插槽關系 Redis將每個鍵的鍵名的有效部分使用CRC16算法計算出哈希值,然后對剩余的16834取余。
查看集群中所有節點信息
[root@dcdfa0e9eb71 redis]# redis-cli -p 9001 127.0.0.1:9001> cluster nodes b8bf4748d7039934d4ba43fe558a464592958eff 127.0.0.1:9004@19004 slave f70b68962d8fb9b485cd420b1731b997feac12ad 0 1640770784000 3 connected abc2fa081d403c505b5d5127d3c3af9ffaa38538 127.0.0.1:9001@19001 myself,master - 0 1640770785000 2 connected 5461-10922 e4256cad47611df0aa3f6a41c89d24b91c1aa89e 127.0.0.1:9000@19000 master,fail - 1640770645974 1640770641000 1 disconnected 1baffc136c23418c05bda6805614fc4a29d02004 127.0.0.1:9005@19005 master - 0 1640770784709 7 connected 0-5460 0071f328a2c0a6a58cfe373ce0d8c6137bf15e0c 127.0.0.1:9003@19003 slave abc2fa081d403c505b5d5127d3c3af9ffaa38538 0 1640770782000 2 connected f70b68962d8fb9b485cd420b1731b997feac12ad 127.0.0.1:9002@19002 master - 0 1640770785716 3 connected 10923-16383查看集群是否啟用
127.0.0.1:9002> info cluster # Cluster cluster_enabled:1 #1表示啟用查看插槽分配情況
127.0.0.1:9002> cluster slots 1) 1) (integer) 02) (integer) 54603) 1) "127.0.0.1"2) (integer) 90053) "1baffc136c23418c05bda6805614fc4a29d02004" 2) 1) (integer) 54612) (integer) 109223) 1) "127.0.0.1"2) (integer) 90013) "abc2fa081d403c505b5d5127d3c3af9ffaa38538"4) 1) "127.0.0.1"2) (integer) 90033) "0071f328a2c0a6a58cfe373ce0d8c6137bf15e0c" 3) 1) (integer) 109232) (integer) 163833) 1) "127.0.0.1"2) (integer) 90023) "f70b68962d8fb9b485cd420b1731b997feac12ad"4) 1) "127.0.0.1"2) (integer) 90043) "b8bf4748d7039934d4ba43fe558a464592958eff"故障恢復
在上一個集群中,每個節點都會定期的向其他節點發送ping名,并通過有沒有收到回復來判斷目標是否下線。
具體來說,集群中每個節點每隔一秒就會隨機選擇5個節點,然后選擇最久沒有響應節點發送ping命令。
一定時間內節點沒有響應回復,則發起PING命令的節點會認為目標節點疑似下線。
如何確定某個節點下線?
1)一旦節點A認為節點B疑似下線,就會在集群中廣播該消息,所有其他節點收到該消息后都會記錄這一信息;
2)當集群中的某一個節點C收到半數以上的的節點認為B是疑似下線的狀態,就會將B標記為下線,并且向集群中的其他節點傳播該信息,從而使B在整個集群下線。
- 在集群中,當一個主數據庫下線時,就會出現一部分插槽無法寫入的問題。如果該主數據庫至少有一個從數據庫,集群就進行故障恢復操作來將其中一個從數據庫切換為主數據庫。
| Redis-server | 是 | 127.0.0.1 | 6379 |
| Redis-server | 否 | 127.0.0.1 | 6380 |
| Redis-server | 否 | 127.0.0.1 | 6381 |
| Sentinel | - | 127.0.0.1 | 26379 |
| Sentinel | - | 127.0.0.1 | 26380 |
| Sentinel | - | 127.0.0.1 | 26381 |
總結
- 上一篇: laravel 框架基础 学习整理
- 下一篇: 高性能 Redis 实战