redis常用命令備忘錄

1.啟動

1.1windows版本啟動命令

????redis-server.exe ./redis.windows.conf

????redis-cli??

2.數(shù)據(jù)類型

?2.1.string? ??

????????格式? set key value [EX seconds][PX milliseconds] [NX|XX]

????????EX seconds : 將鍵的過期時間設(shè)置為 seconds 秒。

????????PX milliseconds : 將鍵的過期時間設(shè)置為 milliseconds 毫秒。

????????NX : 只在鍵不存在時, 才對鍵進(jìn)行設(shè)置操作。 執(zhí)行 SET key value NX 的效果等同于執(zhí)行 SETNX key value

????????XX : 只在鍵已經(jīng)存在時, 才對鍵進(jìn)行設(shè)置操作。?

在 Redis 2.6.12 版本以前, SET 命令總是返回 OK 。?

? ? ? ? set name dubian? ? //添加

????????get name? ? //獲取

? ? ? ? exists name? ? //判斷key是否存在 0 存在 1 不存在

? ??????del name //刪除數(shù)據(jù)結(jié)構(gòu),所有數(shù)據(jù)結(jié)構(gòu)都用該命令刪除

? ? ? ? mset k1 v1 k2 v2 k3 v3 //批量讀寫可節(jié)省網(wǎng)絡(luò)消耗開銷

? ? ? ? mget k1 k2 k3

? ? ? ?過期策略

? ? ? ? expire name 5 //5s后過期

? ? ? ? setex name 5 dubian //等價于set+expire

? ? 計數(shù)

? ? ? ? 如果value是整數(shù),可對value進(jìn)行自增操作,范圍是singed long最大最小值,超過報錯

? ? ? ? set age 30? //OK

? ? ? ? incr age //31

? ? ? ? incrby age 4 //35

? ? ? ? incrby age -5 //30

2.2.list(列表)

? ? 特點:相當(dāng)于java的LinkedList,增刪快定位慢。列表元素為空數(shù)據(jù)結(jié)構(gòu)自動刪除,內(nèi)存回收(redis所有數(shù)據(jù)結(jié)構(gòu)都有此特性)。list底層是一個快速鏈表quicklist,在元素較少時會使用一塊連續(xù)的內(nèi)存存儲,稱為壓縮列表ziplist,當(dāng)數(shù)據(jù)較多才會變?yōu)閝uicklist。

? ? 隊列FIFO:右邊進(jìn)左邊出?

????棧:右邊進(jìn)右邊出

? ? rpush key1 v1 v2 v3 //添加元素

? ? llen key1? ?//獲取長度

? ? rpop key1? ? ? ?lpop key1 //彈出元素

? ? rpush key1 v1? ? ? ? rpush key1 v1? //添加元素

? ? lindex key1 1? ? //返回v2,相當(dāng)于java鏈表的get(index)

? ? ltrim key1 1 2? //對列表進(jìn)行截斷操作,返回OK 。 Index可為負(fù)數(shù),-1表示倒數(shù)第一個元素,可用于實現(xiàn)一個定長列表

? ? lrang key1 0 -1 //獲取所有元素,O(n)謹(jǐn)慎使用

2.3.hash(字典)

? ? 特點:相當(dāng)于java的HashMap,同樣是數(shù)組+鏈表的二維結(jié)構(gòu),不同的是,redis的字典采用的是漸進(jìn)式rehash。漸進(jìn)式rehash查詢時會同時查詢兩個hash結(jié)構(gòu),然后在后續(xù)的定時任務(wù)和hash子指令中,循序漸進(jìn)的將舊hash內(nèi)容遷移到新hash中。

????hset key1 field1 v1? //如果字符串包含空格需要藥引號括起來

????hgetall key1 //獲取entry field與value間隔出現(xiàn)

????hget key1 field1 //獲取指定field值

????hmset key1 field1 v1 field2 v2 field3 v3 //批量set

? ? hincrby dubian age 1 //單個field可進(jìn)行計數(shù)

2.4.set(集合)

? ? ? ? 特點:相當(dāng)于java里的HashSet,其內(nèi)部的鍵值是唯一無序的,內(nèi)部實現(xiàn)相當(dāng)于一個特殊字典,字典中所有的value都是NULL。set結(jié)構(gòu)可以用來存儲中獎用戶id,因為有去重功能,保證同一個用戶不會中獎兩次。

? ? sadd key1 m1 m2 m3 //key1中若存在該member則返回0,否則返回1成功

? ? smembers key1 //獲取所有member

? ? sismember key1 m1 //查詢某個member是否存在,存在返回1,不存在返回0

? ? scard key1 //計數(shù)

2.5.zset有序列表

? ? 特點:類似于SortSet和HashMap的結(jié)合體,一方面它是set,保證了內(nèi)部member的唯一性,另一方面它可以給每個member一個score,代表這個member的排序權(quán)重。它內(nèi)部實現(xiàn)用一種叫跳躍鏈表的數(shù)據(jù)結(jié)構(gòu)。

? ? 格式:zadd key [NX|XX] [CH] [INCR] score member [score member ...]

? ? zadd key1 9.0 member1 8.0 member2 10.0 member3//return 1

? ? zrevange key1 0 -1 //按score降序排列,參數(shù)區(qū)間為排名范圍 ,相反指令zrange則為升序排列

? ? zcard key1 //計數(shù)

? ? zrank key1 member1 //查看member1的排名,socre越高返回值越高

????格式:zrangebyscore key min max [WITHSCORES] [LIMIT offset count]

????zrangebyscore key1 0 9 //根據(jù)分值區(qū)間遍歷zset,WITHSCORES同時返回對于score值,LIMIT設(shè)置偏移量及返回個數(shù)?

3.過期時間

? ? Redis的所有數(shù)據(jù)結(jié)構(gòu)都可以設(shè)置過期時間,需要注意過期時間是以對象為單位,比如一個hash結(jié)構(gòu)的過期時間是整個hash對象的過期,另外如果設(shè)置了過期時間后你調(diào)用set方法修改了它,它的過期時間會消失。

? ? 格式:expire key seconds

? ? expire key1 10? //設(shè)置10秒后過期

? ? ttl key1 //查看對象的過期時間

4.分布式鎖

? ? redis實現(xiàn)分布式鎖的原理是在redis里面占一個“坑”,當(dāng)別的進(jìn)程也要進(jìn)來占時,發(fā)現(xiàn)已經(jīng)有人蹲在那里了,就只能放棄或稍后再試。占坑一般使用setnx指令與expire設(shè)置過期時間,用完調(diào)用del釋放這個坑。但是這里有個問題,當(dāng)邏輯執(zhí)行到中間出現(xiàn)異常時,可能會導(dǎo)致del指令沒有被調(diào)用,這樣就會陷入死鎖,而且還有一個問題,如果在setnx和expire直接服務(wù)器進(jìn)程突然掛掉,也可能會造成死鎖。所幸redis在2.8版本作者加入了set的擴(kuò)展參數(shù),使得setnx與expire可以一起執(zhí)行。

? ? 另外,也可以使用lua腳本解決一致性問題。

? ? redis中的lua腳本使用格式如下:

? ? eval script numkeys key [key ...] arg [arg ...]? //其中script是lua命令,numkeys聲明key數(shù)量,key列表,參數(shù)列表

? ? EVAL "redis.call('setnx',KEYS[1],ARGV[1]);redis.call('expire',KEYS[1],ARGV[2]);" 1 key1 value1 60? ?//該語句設(shè)置key為key1的過期時間為60秒。

? ? 分布式鎖的可重入性:可重入性是指在持有鎖的情況下再次請求加鎖,如果一個鎖支持在同一個線程多次加鎖,那么這個鎖就是可重入的。比如java語言里的ReentrantLock,redis分布式鎖如果需要支持可重入,需要對客戶端的set方法進(jìn)行包裝,使用線程ThreadLocal變量存儲當(dāng)前持有鎖的value。

redis的分布式鎖實現(xiàn)可參考:https://github.com/HZ00M/springboot-demo的RedisWithReentrantLock對象。

5.延時隊列

? ? 延時隊列一般使用Rabbitmq和kafka中間件實現(xiàn),相比于專業(yè)的消息隊列,并沒有非常多的高級特性,也沒有ack保證,該內(nèi)容僅作為一項知識點,作為參考。

? ? redis使用rpush/lpush操作入隊,lpop/rpop操作來出隊,但是會出現(xiàn)一個問題,如果隊列為空,那pop操作將會陷入死循環(huán),拉高客戶端CPU和redis的QPS。

? ? 因此,redis提供了blpop/brpop來阻塞讀,b就是blocking。另外如果出現(xiàn)空閑連接,一般服務(wù)器會主動斷開連接,bpop操作會拋出異常來,所有編寫客戶端時需要注意捕獲異常,進(jìn)行重試。

? ? 延時隊列也可以通過zset(有序列表)來實現(xiàn)??梢詫⑾⒒?qū)ο笮蛄谢梢粋€字符串作為zset的value(可使用fastjson進(jìn)行序列化),到期時間做為score,然后使用多個線程輪詢zset獲取到期的任務(wù)進(jìn)行處理,多線程可保證萬一一個線程掛了還有其他線程繼續(xù)處理,因為有多個線程,需要考慮并發(fā)爭搶任務(wù),保證任務(wù)不能被多次執(zhí)行。redis的zrem方法是多線程爭搶任務(wù)的關(guān)鍵,它的返回值決定了當(dāng)前實例有沒有搶到任務(wù)。(獲取到為1,獲取不到為0)

redis的延時隊列實現(xiàn)可參考:https://github.com/HZ00M/springboot-demo的RedisDelayQueue對象。

6.位圖

? ? 介紹:redis提供了位圖數(shù)據(jù)結(jié)構(gòu)(位圖不是特殊的數(shù)據(jù)結(jié)構(gòu),它的內(nèi)容其實就是普通的字符串,也就是byte[]數(shù)組) ,我們可以使用普通的get/set獲取或設(shè)置整個位圖的內(nèi)容? ?redis的位數(shù)組是自動擴(kuò)展,如果設(shè)置某個偏移值超出了現(xiàn)有的內(nèi)容范圍,就會自動進(jìn)行零擴(kuò)充。

????使用場景:如記錄簽到信息可大大節(jié)省存儲空間。

? ? 獲取某個字符的ASCII碼和二進(jìn)制數(shù)組可用Integer.valueOf(c)和Integer.toBinaryString(c)。

? ? 比如字符‘h’的ASCII碼為104,二進(jìn)制數(shù)組為01101000。

? ? 單個bit操作

????格式:setbit key offset value? //按位設(shè)值,offset 偏移量 value 0或1

? ? ? ? ? ? ? ?getbit key offset? //按位取

? ? 如設(shè)置'h',其二進(jìn)制數(shù)組2/3/5位為1

? ? setbit hello 1 1 ;setbit hello 2 1;setbit hello 4 1;? //相當(dāng)于set hello h

? ? get hello //返回h(此為整取,也可以使用bitget 命令進(jìn)行按位取)

? ? 統(tǒng)計與查找:redis提供了位圖統(tǒng)計指令bitcount和位圖查找指令bitpos,bitcount用于統(tǒng)計指定范圍內(nèi)1的個數(shù),bitpos查找用戶從哪一天開始簽到,如果指定了范圍參數(shù)[start,end],就可以統(tǒng)計某個時間范圍內(nèi)簽到多少天,但是start和end是字節(jié)索引,也就是說指定范圍必須是8的倍數(shù)。

? ? bitcount格式:bitcount key [start end]

? ? set sign hello?

? ? bitcount sign //返回21

? ? bitcount 0 1 //前兩個字符中1的位數(shù)

? ? bitpos格式:bitpos key bit [start] [end]

? ? bitpos sign 1 1 1 //從第二個字符算起,第一個1位

? ? bitpos sign 1 2 2 //從第三個字符算起,第一個1位

? ? 魔術(shù)指令bitfield:可以一次進(jìn)行多次設(shè)置(setbit)和獲?。╣etbit),bitfiled有三個子指令,分別是get/set/incrby,它們都可以對為片段進(jìn)行讀寫,但是最多只能處理64個連續(xù)的位。

? ? bitfield格式:bitfield key [get type offset] [set type offset value] [incrby type offset increment]

? ? 前面的設(shè)置‘h’可改為bitfield hello set u1 1 1 set u1 2 1 set u1 4 1,效果是一樣的。

? ? bitfield hello get u4 0 //從第一位開始取4位,結(jié)果是無符號數(shù)

? ? bitfield hello get i4 0? //從第一位開始取4位,結(jié)果是有符合數(shù)

? ? 所謂的有符號數(shù)是位數(shù)組中第一位是符號位,剩下的才是值,如第一位是1,那就是負(fù)數(shù),有符號位最多可以取64位,無符號數(shù)最多可取63位。

? ? incrby子指令用來對指定范圍的位進(jìn)行自增操作,既然是自增,就有可能溢出,如果增加的是正數(shù),就有可能上溢,增加的是負(fù)數(shù),就有可能下溢。如果溢出,就將溢出的符號位丟掉,如果是8位的無符號數(shù)255,加一就會溢出,全部變成零。如果有符號位數(shù)127加一就會溢出,變成-128。redis提供三個溢出策略,默認(rèn)是折返(wrap),還可以選擇失敗不執(zhí)行,還可以進(jìn)行飽和截斷(sat)

? ? 如:bitfield hellow overflow sat incrby u4 2 1 //從第三位起取4位加1,溢出則保留最大值

7.HyperLogLog

? ? 介紹:HyperLogLog提供不精確的去重技術(shù)方案(標(biāo)準(zhǔn)誤差0.81%),是redis的高級數(shù)據(jù)結(jié)構(gòu)。

? ? 使用場景:計算UV(PV是頁面訪問量,UV是用戶量),如使用set存儲UV,會很浪費存儲空間,因此可以使用內(nèi)存占用率低的HyperLogLog。

? ? HyperLogLog格式:pfadd key member (對應(yīng)sadd)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pfcount key (對應(yīng)scard)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pfmerge distkey sourcekey [sourcekey ...](用于多個pf計數(shù)值得累加)

8.布隆過濾器

? ? 介紹:布隆過濾器可以理解為一個不name精確的set,在redis4.0之后才提供。布隆過濾器有兩個基本指令,bf.add添加元素,bf.exists查詢元素是否存在,它的用法和set集合的sadd和sismember差不多,注意一次只能添加一個元素,如需添加多個要用到bf.madd,同樣查詢多個使用bf.mexists。

? ? bf.add key1 member1

? ? bf.exists key1 member1 //1存在0不存在

? ? bf.madd key1 member1 member2 ...

? ? bf.mexists key1 member1 member2 //返回多個值 1 1 ...

? ? 布隆過濾器有一定的誤判性,因此redis還提供了自定義參數(shù)的布隆過濾器,需要我們在add之前使用bf.reserve顯式創(chuàng)建,bf.reserve有三個參數(shù),分別是key,error_rate和initial_size。錯誤率越低需要的空間越大,initial_size表示預(yù)計的元素數(shù)量,當(dāng)實際數(shù)量超出這個數(shù)值時,誤判率會上升。如不使用bf.reserve,默認(rèn)的error_rate是0.01,initial_size是100。

? ? 擴(kuò)展:布隆過濾器在NoSQL領(lǐng)域使用非常廣泛,我們平時用到的HBase,Cassandra,LevelDB,RocksDB內(nèi)部都有布隆過濾器結(jié)構(gòu)。布隆過濾器可以顯著降低數(shù)據(jù)庫IO請求數(shù)量。

9.限流策略

? ? redis的限流可使用zset實現(xiàn),通過score圈出一個時間窗口,窗口外的數(shù)據(jù)都可以砍掉,而value只要保證唯一性即可,如使用時間戳。

? ? 具體方法:用一個zset結(jié)構(gòu)記錄用戶的行為歷史,每一個行為作為zset中的一個key,同一個用戶的同一個行為用一個key記錄。通過統(tǒng)計窗口內(nèi)行為數(shù)量與閾值進(jìn)行比較,就可以得出當(dāng)前行為是否允許。?

? ? redis4.0提供了一個限流redis模塊,它叫redis-cell,該模塊使用了漏斗算法。

? ??漏桶算法(Leaky Bucket):主要目的是控制數(shù)據(jù)注入的速率,平滑操作次數(shù)。漏桶算法提供了一種機制,通過它,突發(fā)流量可以被整形以便提供一個穩(wěn)定的流量。漏桶算法的示意圖如下:

? ? 該模塊只有一條指令 cl.throttle

? ? cl.throttle key1 15 30 60 1 // 15為容量,30/60為速率 ,60秒內(nèi)30次操作 ,1 quota 多長時間漏斗完全空出來。返回值為【0,15,14,-1,2 】返回值第一個參數(shù)0表示允許,1表示拒絕。15表示漏斗容量,14表示剩余容量,第四個參數(shù)表示多長時間后可以再試(有空間了),第五個參數(shù)表示多長時間后漏斗完全空出來

? ? 上面這條指令的意思是允許key1的操作次數(shù)每60秒最多30次,初始容量為15是說一開始連續(xù)操作15次后才開始受速率影響,在執(zhí)行限流指令時,如果被拒絕了,就需要丟棄或重試,可直接用第四個參數(shù)的值進(jìn)行sleep后重試。

10.GeoHash

? ? GeoHash算法:業(yè)界通用的地理位置距離排序算法,算法將二維的經(jīng)緯度映射到一維數(shù)組,這樣就將所有的元素都掛載到一條直線上。

? ? Geo的內(nèi)部結(jié)構(gòu)實際上就是一個zset結(jié)構(gòu),score是geohash的52位整數(shù)值,value是元素的key通過score排序就可以得到坐標(biāo)附近的其他元素,并通過score還原成坐標(biāo)值就可以得到元素的原始坐標(biāo)。

? ? Geo有6條指令,格式如下:

? ? 添加元素:geoadd key longtitude latitude member [ longtitue latituemember...]

? ? 計算距離:geodist key member1 member2 [unit]

? ? 獲取元素坐標(biāo):geopos key member1 [member2 ...]

? ? 獲取geohash值:geohash key member1 [member2 ...]

? ? 獲取指定元素附近的元素:georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [count value] asc|desc?

? ? 根據(jù)坐標(biāo)值查詢附近元素【附近的車】【附近的餐館】:

? ? georadius key longtitue latitue radius m|km|ft|mi?[withdist] [withhash] [count value]?asc|desc

? ? geo數(shù)據(jù)如果過大,建議進(jìn)行拆分,且數(shù)據(jù)使用單獨的redis部署,不使用集群環(huán)境。

11.檢索

????keys格式:keys pattern? ? ?(采用遍歷算法,時間復(fù)雜度為O(n))

? ? scan格式:scan cursor [match pattern] [count count] (count不是限定數(shù)量,而是限定服務(wù)器單次遍歷字典槽位的數(shù)量,如果游標(biāo)的返回值不為零,說明遍歷還沒結(jié)束)

? ? scan采用的是高位進(jìn)位加法來遍歷,高位進(jìn)位可避免擴(kuò)容和縮容時槽位的遍歷和遺漏。? ??

? ? 大key掃描:大key掃描是檢索redis中的大對象,可在客戶端啟動時加上--bigkeys,如果擔(dān)心這個指令會抬升redis的ops,還可增加一個參數(shù) -i 0.1,上面指令的意思是每隔100條scan指令就會休眠0.1s,ops就不會劇烈抬升,但掃描的時間會變長。

12.持久化

? ? redis的持久化機制有兩種,第一種是快照,第二種是aof日志??煺帐且淮稳總浞荩琣of日志是連續(xù)的增量備份。

? ?快照原理: redis使用操作系統(tǒng)的多進(jìn)程COW(copy on write)機制來實現(xiàn)快照持久化。redis在持久化時會調(diào)用glibc的函數(shù)fork產(chǎn)生一個子進(jìn)程,快照持久化操作完全交給子進(jìn)程來處理,子進(jìn)程剛剛產(chǎn)生時,它與父進(jìn)程共享內(nèi)存里的代碼段和數(shù)據(jù)段,子進(jìn)程在做數(shù)據(jù)持久化時不會修改現(xiàn)有的內(nèi)存數(shù)據(jù)結(jié)構(gòu),它只是對數(shù)據(jù)結(jié)構(gòu)進(jìn)行遍歷讀取,然后序列化到磁盤中。當(dāng)父進(jìn)程對數(shù)據(jù)進(jìn)行修改時,會將被修改的數(shù)據(jù)共享頁復(fù)制一份分離出來,然后對這個復(fù)制頁面進(jìn)行修改,隨 著越來越多的共享頁面的分離,內(nèi)存會持續(xù)增長,但最高不會原數(shù)據(jù)內(nèi)存的2倍??煺諘G失大量數(shù)據(jù)。? ??

aof原理:aof日志存儲的是redis的順序指令序列,只記錄對內(nèi)存數(shù)據(jù)進(jìn)行修改的指令。在redis長期運行過程中,aof會變得越來越長,如果實例宕機重啟,aof日志會非常耗時,此時需要對aof日志進(jìn)行瘦身,redis提供bgrewriteaof?指令對aof日志進(jìn)行瘦身 。

? ? Linux的glibc提供了fsync(int fd)函數(shù)可以將指定內(nèi)容強制從內(nèi)核緩存刷到磁盤,只要redis實時調(diào)用fsync函數(shù)就可以保證aof日志不丟失。但fsync是一個磁盤io操作,它很慢,如果redis每執(zhí)行一條指令就要fsync一次,那redis的高性能地位就不保了。redis默認(rèn)每隔一秒fsync一次,該周期是可配置的,redis另外還提供了兩個策略:一個是永不,讓操作系統(tǒng)決定合適同步磁盤,很不安全;另外一個是一個指令就fsync一次,但生產(chǎn)環(huán)境最好不要使用??稍谂渲梦募锌吹竭@幾個配置:

#appendfsync always? ??

appendfsync everysec

# appendfsync no????

redis4.0混合持久化。原理是redis重啟的時候先加載快照內(nèi)容(.rdb),然后再重放增量aof日志。

13.管道

????管道本質(zhì)是將多個操作指令由客戶端封裝成數(shù)據(jù)包一次性發(fā)送給服務(wù)端進(jìn)行批量操作,達(dá)到節(jié)省io的目的,管道中指令越多,效果越好。

redis自帶了壓力測試工具redis-benchmark?,使用這個工具可以進(jìn)行管道測試

? ? >redis-benchmark -t set -q //返回 set:51452 requests per second

? ? 我們加入管道選項-P參數(shù),它表示單個管道內(nèi)并行請求的數(shù)量,當(dāng)P=2,QPS可達(dá)到9w/s。

14.事務(wù)

? ? redis同樣提供了事務(wù)機制,有三個指令,分別是multi/exec/discard。multi表示事務(wù)開始,exec表示事務(wù)執(zhí)行,discard表示事務(wù)丟棄。

? ? redis的事務(wù)失敗后,后面的指令還會繼續(xù)執(zhí)行,使用redis的事務(wù)不具備原子性,只能滿足隔離性(當(dāng)前事務(wù)不被其他事務(wù)打斷的權(quán)利)

? ? redis中的樂觀鎖:redis提供了watch機制,watch會在事務(wù)開始前盯住一個或多個鍵,當(dāng)事務(wù)執(zhí)行時,redis會檢測關(guān)鍵字自watch之后,是否被修改了(包括當(dāng)前事務(wù)所在的客戶端),如果關(guān)鍵字被人動過了,exec就會返回Null,告知客戶端事務(wù)執(zhí)行失敗,這時客戶端可進(jìn)行重試。

15.主從同步

????分布式理論的基石 --------? CAP原理

? ? ? ? C - Consistent , 一致性

? ? ? ? A - Availability,可用性

? ? ? ? P - Partiton tolerance,分區(qū)容忍性

? ? 分布式系統(tǒng)的節(jié)點往往都是分布在不同的機器上進(jìn)行網(wǎng)絡(luò)隔開的,這意味著必然有網(wǎng)絡(luò)斷開的風(fēng)險,這個斷開的場景叫做網(wǎng)絡(luò)分區(qū)。

? ? 在發(fā)送網(wǎng)絡(luò)分區(qū)時,兩個分布式節(jié)點無法互相通信,我們對一個節(jié)點進(jìn)行修改操作將無法同步到另外一個節(jié)點,所以數(shù)據(jù)的一致性無法得到滿足,因為兩節(jié)點數(shù)據(jù)不再保持一致,除非我們犧牲可用性,也就是暫停分布式節(jié)點服務(wù),在發(fā)生網(wǎng)絡(luò)分區(qū)時,不再提供修改數(shù)據(jù)功能,直到網(wǎng)絡(luò)恢復(fù)。

? ? 最終一致:redis的主從數(shù)據(jù)是異步同步的,所以分布式的redis不滿足一致性要求。當(dāng)客戶端從redis主節(jié)點修改了數(shù)據(jù)后,立即返回,即使在主從網(wǎng)絡(luò)斷開的情況下,主節(jié)點依舊可以正常對外提供服務(wù),所以redis滿足可用性。從節(jié)點在網(wǎng)絡(luò)恢復(fù)后會采用多種策略努力追趕落后的數(shù)據(jù)。

? ? 主從同步:redis支持主從同步和從從同步。

? ? 增量同步:redis同步的是指令流,主節(jié)點會將修改性的指令記錄在本地內(nèi)存buffer中,如何異步的將buffer中的指令記錄同步到從節(jié)點,從節(jié)點一步步執(zhí)行同步指令達(dá)到和主節(jié)點一樣的狀態(tài),同時反饋自己同步到哪里了(偏移量)。redis復(fù)制內(nèi)存buffer是一個定長的環(huán)形數(shù)組,如果因為網(wǎng)絡(luò)不好,redis主節(jié)點上那先沒有同步的指令可能會被后續(xù)的指令覆蓋,這時候就需要更復(fù)雜的同步機制,快照同步。

? ? 快照同步:快照同步是非常消耗資源的操作,它首先會進(jìn)行一次bgsave(產(chǎn)生.rdb),然后將快照傳送到從節(jié)點。快照接受完畢后,先清空當(dāng)前內(nèi)存,然后執(zhí)行一次全量加載,加載完成后通知主節(jié)點繼續(xù)進(jìn)行增量同步。但如果快照時間過長或者復(fù)制buffer太小,一樣會產(chǎn)生覆蓋問題,因此務(wù)必配置一個合適的復(fù)制buffer大小。

? ? 增加從節(jié)點:當(dāng)從節(jié)點剛加入集群時,它必須先進(jìn)行一次快照同步,完成后才進(jìn)行增量同步,redis2.8.18版本后快照文件將直接通過套接字傳輸減少主節(jié)點的io操作。

? ? wait指令:wait指令可以讓異步復(fù)制變成同步復(fù)制,確保強一致性。

? ? wait格式:wait numslaves timeout //numslave確保多少個從節(jié)點同步?jīng)]有滯后,timeout設(shè)置為0表示一直等待。

? ? 配置主從方式::

? ? ? ? 1:slaveof指令:從服務(wù)器啟動后,執(zhí)行slaveof host port?

? ? ? ? 2:配置方式:將

# slaveof <masterip> <masterport>

? ? ? ? ? ? ? ? ? ? ? ? ? ? 改成

slaveof 127.0.0.1 6379

? ?? ????????????????????????????????masterauth redis

????主從復(fù)制是系統(tǒng)數(shù)據(jù)安全的保障,必須認(rèn)真對待。

16.Sentinel(哨兵模式)

? ? 哨兵模式可以在故障發(fā)生時自動進(jìn)行主從切換,redis提供的redis sentinel可以看成一個zookeeper集群,一般由3~5個節(jié)點組成。當(dāng)客戶端連接集群時,首先連接sentinel,通過sentinel來查詢主節(jié)點地址,然后才進(jìn)行交互。

? ? 由于redis采用異步復(fù)制,無法保證消息完全不丟失,但可以保證消息少丟失。它有兩個選項可以限制主從延遲過大。

? ? min-slaves-to-write 1

? ? min-slaves-max-lag 10

? ? 第一個參數(shù)表示主節(jié)點至少有一個從節(jié)點在進(jìn)行正常復(fù)制,否則就停止對外寫服務(wù)。

? ? 何為正常復(fù)制,這個參數(shù)就是又第二個參數(shù)控制的,它的單位是秒,表示如果10秒內(nèi)沒有收到從節(jié)點的反饋,意味著同步不正常。

17.一主二從三哨兵模式搭建

? ? 假設(shè)有三臺服務(wù)器,ip分別為????127.1.1.1????,????127.1.1.2????,????127.1.1.3:

? ? 主庫配置:

? ? ? ? # 1. 修改綁定ip為服務(wù)器內(nèi)網(wǎng)ip地址,做綁定,三臺各自填寫各自的ip地址

????????bind 172.1.1.1

????????# 2. 保護(hù)模式修改為否,允許遠(yuǎn)程連接

????????protected-mode no

????????# 3. 設(shè)定密碼

????????requirepass"123"

????????# 4. 設(shè)定主庫密碼與當(dāng)前庫密碼同步,保證從庫能夠提升為主庫

? ? ? ? masterauth"123"

????????# 5. 打開AOF持久化支持

????????appendonly yes

兩個從庫配置:

? ??????# 1. 綁定的地址

????????bind172.1.1.2

????????# 2. 保護(hù)模式修改為否,允許遠(yuǎn)程連接

????????protected-mode no

????????# 3. 設(shè)定sentinel myid 每個都不一樣?

????????sentinel myid 04d9d3fef5508f60498ac014388571e719188527

????????# 4. 設(shè)定監(jiān)控地址,為對應(yīng)的主redis庫的內(nèi)網(wǎng)地址

????????sentinel monitor mymaster 172.1.1.1 6379 2

????????# 5. 設(shè)定5秒內(nèi)沒有響應(yīng),說明服務(wù)器掛了,需要將配置放在sentinel monitor master 127.0.0.1 6379 1下面

????????sentinel down-after-milliseconds mymaster 5000

????????# 6. 主數(shù)據(jù)庫密碼,需要將配置放在sentinel monitor master 配置下面

????????sentinel auth-pass mymaster 123

????????# 7. 設(shè)定15秒內(nèi)master沒有活起來,就重新選舉主

????????sentinel failover-timeout mymaster 15000

????????# 8. 表示如果master重新選出來后,其它slave節(jié)點能同時并行從新master同步緩存的臺數(shù)有多少個,顯然該值越大,所有slave節(jié)點完成同步切換的整體速度越快,但如果此時正好有人在訪問這些slave,可能造成讀取失敗,影響面會更廣。最保定的設(shè)置為1,只同一時間,只能有一臺干這件事,這樣其它slave還能繼續(xù)服務(wù),但是所有slave全部完成緩存更新同步的進(jìn)程將變慢。

????????sentinel parallel-syncs mymaster 2

18.消息隊列Stream

? ? 介紹:redis5.0提供的一個新的數(shù)據(jù)結(jié)構(gòu)stream,是一個強大的支持多播的可持久化消息隊列,它將所有加入的消息都串起來,每個消息都有一個唯一的ID和對應(yīng)的內(nèi)容。消息是持久化的,redis重啟之后,內(nèi)容還在。每個stream都有一個唯一的名稱,它就是redis的key,在我們首次使用xadd時自動創(chuàng)建。

? ? 每個stream可以掛多個消費組,每個消費組都有個游標(biāo)last_delivered_id在stream數(shù)組上往前移動,表示當(dāng)前消費組已經(jīng)消費到哪條消息了。每個消費組都有一個stream內(nèi)唯一的名稱,消費組不會自動創(chuàng)建,它需要單獨的指令xgroup create進(jìn)行創(chuàng)建需要指定從stream的哪條消息開始消費。這個id用來初始化last_delivered_id變量。

? ? 每個消費組的狀態(tài)都是相互獨立的,也就是說stream內(nèi)部的消息會被每個消費組消費到。

? ? 同一個消費組可以掛接多個消費者,這些消費者之間是競爭關(guān)系,消費者內(nèi)部有一個pending_ids(Pending Entries List),它記錄了當(dāng)前已經(jīng)被客戶端讀取的消息,但是還沒有ack,這是一個很核心的數(shù)據(jù)結(jié)構(gòu),它用來確??蛻舳酥辽傧M了一次消息。

? ? 增刪查改:

? ? 1.xadd [maxlen len]? key? #|*? ?key1 value1 [key2 value2 ...]? //追加消息, *和#表示服務(wù)器自動生成ID,maxlen提供一個定長,可以將老的消息干掉,確保不會超出指定長度

? ? 2.xdel key? ID //刪除消息

? ? 3.xrange? - +? //獲取消息列表,會自動過濾已經(jīng)刪除的消息,+ -表示最大值和最小值,也可以指定ID如xrange? -? 1482837165811-0

? ? 4.xlen? key? //消息長度,刪除操作對長度沒有影響

? ? 5.del key? ?//刪除stream

? ? 6.xread count limit streams key ID //從stream頭部讀取limit?條信息,當(dāng)使用xread時,可以忽略消費組

? ? ? ? xread block 0 count 1 streams key1 $ //從尾部阻塞等待新消息到來,block 0 表示永遠(yuǎn)阻塞,block 1000表示阻塞1S,一秒內(nèi)沒有任何消息到來就返回nil;

? ? 創(chuàng)建消費組:

? ? stream通過xgroup create指令創(chuàng)建消費組,需要傳遞起始ID。

? ? xgroup create key1 group1 0-0 //表示從頭開始消費

? ? xgroup create key1 group2 $? //$表示從尾部開始消費,只接受新消息

? ? xinfo stream key1//獲取stream信息

? ? xinfo groups group1 //獲取stream消費組信息

? ? xreadgroup GROUP group1 comsumer1 count 1 streams key1 > // >表示從當(dāng)前消費組的last_delivered_id后開始讀,每當(dāng)消費者讀取一條消息,last_delivered_id就會前進(jìn)

? ? xinfo comsumers key1 group1 # //查看group1每個消費者的狀態(tài)

? ? xack key1 group1 ID //確認(rèn)一條消息 ,待處理消息(peding)變成了4條?

19.查詢指令(info)

? ? info指令顯示的信息非常多,分為9大塊:

? ? 1.server服務(wù)器運行環(huán)境參數(shù)

? ? 2.clients客戶端相關(guān)信息

? ? 3.memory服務(wù)器運行內(nèi)存統(tǒng)計信息

? ? 4.persistence持久化信息

? ? 5.stats通用統(tǒng)計數(shù)據(jù)

? ? 6.replication主從復(fù)制相關(guān)信息

? ? 7.cpu cpu相關(guān)信息

? ? 8.cluster集群信息

? ? 9.keyspace鍵值對統(tǒng)計數(shù)量信息

? ? info的參數(shù)非常多,以下挑選關(guān)鍵性的、且非常實用的參數(shù)詳解:

?info stats//redis每秒執(zhí)行多少次指令?

? ? instantaneous_ops_per_sec:789 //表示所有客戶端每秒會發(fā)送789條指令到服務(wù)器

? ? info clients //redis連接了多少客戶端

? ? connected_clients:125 //這個就是正在連接的客戶端數(shù)量

? ? client list? ? ?//可以使用這個指令列出所有客戶端的源頭

? ? rejected_connetctions參數(shù)表示因為超出連接數(shù)限制而被拒絕連接的次數(shù),如果這個數(shù)字很大,說明需要調(diào)整maxclients參數(shù)

?info memory//查看內(nèi)存信息

? ? use_memory_human:828.22k? //內(nèi)存分配器(jemalloc)從操作系統(tǒng)分配的內(nèi)存總量

? ? use_memory_rss_human:3.11M? //操作系統(tǒng)看到的內(nèi)存占用,top命令看到的內(nèi)存

? ? use_memory_peak_human:842.11k? //redis內(nèi)存消耗的峰值

? ? use_memory_lua_human:21.00k? //lua腳本占用的內(nèi)存大小

? ? 如果單個redis內(nèi)存占用過大,需要考慮集群

info replication//查看復(fù)制模塊信息

? ? repl_backlog_active:0

? ? repl_blocklog_size:1048489? ? //這個就是擠壓緩沖區(qū)大小

? ? 復(fù)制積壓緩沖區(qū)大小非常重要,它直接影響到主從復(fù)制的效率。積壓緩沖區(qū)是環(huán)形的。

? ? 可查看sync_partial_err變量的次數(shù)確定是否要擴(kuò)大積壓緩沖區(qū),它表示主從半同步復(fù)制失敗的次數(shù)。

集群方案1(codis)

集群方案2(redisCluster)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容