Redis筆記

Redis五大數(shù)據(jù)類型及其常用操作

字符串

set key value ——設(shè)置屬性值
get key ——獲取值
getset key value ——先獲取值再重新設(shè)置值
del key ——?jiǎng)h除
incr key ——自增,如果key不存在,則會創(chuàng)建一個(gè)值為0的變量
decr key ——自減
incrby key number ——變量+number
decrby key number ——變量-number
append key string ——追加字符串
getrange key start end ——獲取[start,end]之間的字符串
setrange key offset value ——將從offset開始的子串設(shè)置為給定值
bitcount key [ start end ] ——統(tǒng)計(jì)二進(jìn)制位串指定范圍內(nèi)的1的二進(jìn)制位的數(shù)量

Hash

hset key k v ——設(shè)置某個(gè)key下的鍵值對
hmset key k v k v... ——設(shè)置某個(gè)key下的幾個(gè)鍵值對
hget key k ——獲取某個(gè)key下的鍵值
hmget key k k... ——獲取某個(gè)key下的幾個(gè)鍵值
hgetall key ——獲取某個(gè)key下的所有鍵值對
hdel key k k ... ——?jiǎng)h除某個(gè)key下的多個(gè)鍵值
hincrby key k number ——給某個(gè)key下的某個(gè)鍵值+number
hexists key k ——判斷某個(gè)鍵是否存在 (1——存在集币,0——不存在)
hlen key ——獲取key的屬性個(gè)數(shù)
hkeys key ——獲取key的所有鍵名稱
hvals key ——獲取key的所有值

list

lpush key v v v ——從左側(cè)插入鏈表
rpush key v v v ——從右側(cè)插入鏈表
lrange key start end —— 返回[start,end]之間的元素
lpop key ——左端彈出
rpop key ——右端彈出
llen key ——獲取鏈表元素個(gè)數(shù)
lpushx key v ——如果key存在則插入到頭部
rpushx key v ——如果key存在則插入到尾部
lrem key number v —— 刪除key中number個(gè)v(number為負(fù)表示從后往前手幢,0表示所有)
lset key index v ——在key的index的位置處設(shè)置v值
linsert key before v1 v2 ——在第一個(gè)v1之前插入v2
linsert key after v1 v2 ——在第一個(gè)v1之后插入v2
rpoplpush key1 key2——將key1的值彈出壓入key
lindex key index ——獲取列表中給定位置上的單個(gè)元素(從0開始)
ltrim key start end ——只保留[start,end]之間的元素
blpop key timeout ——彈出最左端的元素谷市,如果元素不存在將阻塞timeout秒并等待可彈出的元素出現(xiàn)
brpop key timeout ——彈出最右端的元素,如果元素不存在將阻塞timeout秒并等待可彈出的元素出現(xiàn)
rpoplpush source-key dest-key ——將source-key中最右端的元素彈出,壓入到dest-key的最左端
brpoplpush source-key dest-key timeout ——將source-key中最右端的元素彈出,壓入到dest-key的最左端癌幕,如果source-key中元素不存在,將阻塞timeout秒并等待可彈出的元素出現(xiàn)

set

sadd key v v v... ——往集合里面添加元素
srem key v v v ...——?jiǎng)h除
smembers key ——查看
sisimember key v ——判斷是否存在
sdiff key1 key2 ——找出key1中在key2不存在的元素
sinter key1 key2 ——交集
sunion key1 key2 —— 并集
scard key ——數(shù)目
srandmember key——隨機(jī)返回
sdiffstore key1 key2 key3 ——把key2和key3的差集保存到key1
sinterstore key1 key2 key3 ——把key2和key3的交集保存到key1
sunionstore key1 key2 key3 ——把key2和key3的并集保存到key1
spop key ——隨機(jī)移除集合中的一個(gè)元素
smove source-key dest-key item ——如果集合source-key包含元素item昧穿,那么從集合source-key里面移除元素item勺远,并將元素item添加到集合dest-key中

zset(sorted-set)

zadd key n v n v ——添加元素和相應(yīng)的分?jǐn)?shù)
zscore key v ——查看分?jǐn)?shù)
zcard key ——獲取長度
zrem key v v ——?jiǎng)h除
zrange key start end —— 獲取指定位置范圍內(nèi)的值
zrange key start end withscores ——獲取指定范圍內(nèi)的值和分?jǐn)?shù)
zrevrange key start end withscores
zremrangebyrank key start end ——下標(biāo)范圍刪除
zremrangebyscore key starts ends ——分?jǐn)?shù)范圍刪除
zincrby key number v ——v+number
zcount key starts ends ——分?jǐn)?shù)范圍內(nèi)的個(gè)數(shù)
zrank key v —— 返回成員v在有序集合中的排名

常用操作:

keys * ——獲取所有key
del key1 key2 ——?jiǎng)h除
exists key ——是否存在
rename key1 key2 ——重命名
expire key time ——設(shè)置過期時(shí)間
ttl key ——查看剩余時(shí)間
type key——查看類型
select number ——選擇數(shù)據(jù)庫(0-15)
move key number ——將變量移到number數(shù)據(jù)庫

hypeloglog

  • pfadd key v v v :影響基數(shù)估值則返回1否則返回0.若key不存在則創(chuàng)建
  • pfcount key :得到去重后的值
  • pfmerge destkey key key2:合并多個(gè)key

bitmap

  • setbit key index v : 設(shè)置值
  • getbit key index :獲取值
  • bitcount key [start,end] :獲取某個(gè)范圍的1的個(gè)數(shù)
  • bitop op destkey key (op = or,and,not,xor) bitmap 之間的運(yùn)算

發(fā)布與訂閱

subscribe channel [channer...] ——訂閱給定的一個(gè)或多個(gè)頻道
unsubscribe [channer...] ——退訂給定的一個(gè)或多個(gè)頻道,如果沒有指定时鸵,那么退訂所有頻道
publish channel message ——向給定頻道發(fā)送消息
psubscribe pattern [pattern...] ——訂閱與給定模式相匹配的所有頻道
punsubscribe [pattern...] —— 退訂給定的模式胶逢,如果未指定,則退訂所有的模式

Redis注意點(diǎn)

  • 如果用戶對一個(gè)不存在的鍵或者一個(gè)保存了空串的鍵執(zhí)行自增或者自減操作,那么Redis在執(zhí)行操作時(shí)會將這個(gè)鍵的值當(dāng)作是0來處理初坠。如果用戶嘗試對一個(gè)值無法被解釋為整數(shù)或者浮點(diǎn)數(shù)的字符串鍵執(zhí)行自增或者自減操作和簸,那么Redis將向用戶返回一個(gè)錯(cuò)誤。

Redis使用案例

從海量數(shù)據(jù)中查詢某一前綴的key

方法一:利用key查找(不推薦)

keys pattern:查找所有符合給定模式pattern的key

通過這種方式查詢可能會導(dǎo)致查詢時(shí)間過長某筐,導(dǎo)致redis其他服務(wù)卡頓比搭。

方法二:利用scan查找(推薦)

scan cursor [MATCH pattern] [COUNT count]

  • 基于游標(biāo)的迭代器,需要基于上一次的游標(biāo)延續(xù)之前的迭代過程南誊;
  • 以0作為游標(biāo)開始一次新的迭代,直到命令返回游標(biāo)0完成一次遍歷蜜托;
  • 不保證每次執(zhí)行都返回某個(gè)給定數(shù)量的元素抄囚,支持模糊查詢;
  • 一次返回的數(shù)量不可控橄务,只能是大概率符合count參數(shù)幔托。

如何通過Redis實(shí)現(xiàn)分布式鎖

方法一

setnx key value :如果key不存在,則創(chuàng)建并賦值

  • 時(shí)間復(fù)雜度:O(1)
  • 返回值:設(shè)置成功蜂挪,返回1重挑;設(shè)置失敗,返回0棠涮。

expire key seconds

  • 設(shè)置key的生存時(shí)間谬哀,當(dāng)key過期時(shí)(生存時(shí)間為0),會被自動刪除严肪。

方法二

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

  • EX second :設(shè)置鍵的過期時(shí)間為second秒
  • PX millisecond:設(shè)置鍵的過期時(shí)間為millisecond毫秒
  • NX:只有鍵不存在時(shí)史煎,才對鍵進(jìn)行設(shè)置操作
  • XX:只在鍵已經(jīng)存在時(shí),才對鍵進(jìn)行設(shè)置操作
  • SET操作成功完成時(shí)驳糯,返回OK篇梭,否則返回nil

RDB和AOF

由于Redis是內(nèi)存數(shù)據(jù)庫,它將自己的數(shù)據(jù)庫狀態(tài)存儲在內(nèi)存中酝枢,如果不想辦法將存儲在內(nèi)存中的數(shù)據(jù)庫狀態(tài)保存到磁盤里面恬偷,那么一旦服務(wù)器進(jìn)程退出,服務(wù)器中的數(shù)據(jù)庫狀態(tài)也會消失不見帘睦。

RDB

  • SAVE:會阻塞Redis服務(wù)器進(jìn)程袍患,直到RDB文件創(chuàng)建完成為止,在服務(wù)器進(jìn)程阻塞期間官脓,服務(wù)器不能處理任何命令請求协怒。
  • BGSAVE:會派生出一個(gè)子進(jìn)程,然后由子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件卑笨,父進(jìn)程進(jìn)行處理命令請求孕暇。

一旦BGSAVE開始執(zhí)行了,SAVE命令和BGSAVE命令都會被服務(wù)器拒絕,避免產(chǎn)生競爭條件妖滔。如果BGSAVE命令正在執(zhí)行隧哮,那么客戶端發(fā)送的BGREWRITEAOF命令會被延遲到BGSAVE命令執(zhí)行完畢之后執(zhí)行;如果BGREWRITEAOF命令正在執(zhí)行座舍,那么客戶端發(fā)送的BGSAVE命令會被服務(wù)器拒絕沮翔。避免產(chǎn)生大量的磁盤寫入操作。

將某段時(shí)間內(nèi)的所有數(shù)據(jù)持久化到磁盤中曲秉,類似快照的行為采蚀。當(dāng)在進(jìn)行持久化的過程時(shí)有數(shù)據(jù)的更新,會把這些記錄保存到備份文件中承二,最后會把備份文件拿來替換原文件榆鼠。

缺點(diǎn):如果機(jī)器發(fā)生故障,容易丟失某個(gè)時(shí)間段內(nèi)的數(shù)據(jù)亥鸠。

AOF

**將所有寫命令保存到AOF緩沖區(qū)中妆够,根據(jù)appendfsync的值(默認(rèn)為everysec)來對AOF文件同步,由于大量的寫入命令會導(dǎo)致AOF文件過大负蚊,后臺就會開啟一個(gè)子進(jìn)程對原AOF文件進(jìn)行重寫(合并命令)神妹,對文件進(jìn)行壓縮。如果在重寫期間執(zhí)行了寫入命令家妆,會將寫入命令保存到AOF重寫緩沖區(qū)中鸵荠,等到AOF重寫結(jié)束,再將AOF重寫緩沖區(qū)中的內(nèi)容追加到新AOF文件中揩徊,此時(shí)會對父進(jìn)程阻塞腰鬼,最后用新AOF文件替換原AOF文件。

缺點(diǎn):由于恢復(fù)要進(jìn)行的操作較多塑荒,可能會導(dǎo)致主線程阻塞熄赡。

主從配置(docker無redis.conf)

  • docker啟動主redis: docker run -d --name redis-master -p 6379:6379 redis --requirepass "mypassword"
  • docker啟動從redis: docker run -d --name redis-slave -p 6380:6379 redis --requirepass "mypassword"
  • 連接從redis并進(jìn)行配置:
    1. auth <slave-password>
    2. slaveof <master-ip> <master-port>。<master-ip>為主庫服務(wù)ip齿税,<master-port>表示主庫所在端口彼硫,默認(rèn)6379
    3. config set masterauth <master-password>。<master-password>即為主庫訪問密碼

redis.conf相關(guān)配置

##設(shè)置當(dāng)本機(jī)為slav服務(wù)時(shí)凌箕,設(shè)置master服務(wù)的IP地址及端口拧篮,在Redis啟動時(shí),它會自動從master進(jìn)行數(shù)據(jù)同步

    slaveof <masterip> <masterport>

###當(dāng)master服務(wù)設(shè)置了密碼保護(hù)時(shí)牵舱,slave服務(wù)連接master的密碼

    masterauth <master-password>

##你可以配置salve實(shí)例是否接受寫操作串绩。可寫的slave實(shí)例可能對存儲臨時(shí)數(shù)據(jù)比較有用(因?yàn)閷懭雜alve
##的數(shù)據(jù)在同master同步之后將很容易被刪除

slave-read-only yes

# 是否在slave套接字發(fā)送SYNC之后禁用 TCP_NODELAY芜壁?
# 如果你選擇“yes”Redis將使用更少的TCP包和帶寬來向slaves發(fā)送數(shù)據(jù)礁凡。但是這將使數(shù)據(jù)傳輸?shù)絪lave
# 上有延遲高氮,Linux內(nèi)核的默認(rèn)配置會達(dá)到40毫秒
# 如果你選擇了 "no" 數(shù)據(jù)傳輸?shù)絪alve的延遲將會減少但要使用更多的帶寬

repl-disable-tcp-nodelay no

# slave的優(yōu)先級是一個(gè)整數(shù)展示在Redis的Info輸出中。如果master不再正常工作了顷牌,哨兵將用它來
# 選擇一個(gè)slave提升=升為master剪芍。
# 優(yōu)先級數(shù)字小的salve會優(yōu)先考慮提升為master,所以例如有三個(gè)slave優(yōu)先級分別為10窟蓝,100罪裹,25,
# 哨兵將挑選優(yōu)先級最小數(shù)字為10的slave运挫。
# 0作為一個(gè)特殊的優(yōu)先級状共,標(biāo)識這個(gè)slave不能作為master,所以一個(gè)優(yōu)先級為0的slave永遠(yuǎn)不會被
# 哨兵挑選提升為master

slave-priority 100

緩存穿透和緩存雪崩

  • 緩存穿透:指大量查詢不再緩存中存在的數(shù)據(jù)谁帕,此時(shí)會直接查詢數(shù)據(jù)庫口芍。

解決方法:
1.采用布隆過濾器
2.為不存在的數(shù)據(jù)設(shè)置空值

  • 緩存雪崩:大量緩存數(shù)據(jù)過期。

解決方法:
1.加鎖排隊(duì)
2.

布隆過濾器

首先構(gòu)建長度足夠的位陣列雇卷,所有位置的值都為0,然后創(chuàng)建m個(gè)hash函數(shù)颠猴,將所有元素根據(jù)m個(gè)hash函數(shù)得到的指定位位置的值都置為1关划。查詢的時(shí)候,同樣根據(jù)m個(gè)hash函數(shù)得到位位置的值翘瓮,只要其中有0贮折,說明一定不含有該元素,全為1則可能含有资盅。

Redis淘汰機(jī)制

當(dāng)客戶端發(fā)起了需要申請更多內(nèi)存的命令调榄;Redos檢查內(nèi)存使用情況,如果已使用的內(nèi)存大于maxmemory則開始根據(jù)用戶配置的不同淘汰策略來淘汰內(nèi)存呵扛,從而換取一定的內(nèi)存每庆;如果之前都沒問題,則這個(gè)命令執(zhí)行成功今穿。

  • Volatile-lru:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰缤灵;
  • Volatile-ttl:從已設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰;
  • Volatile-random:從已設(shè)置過期時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰蓝晒;
  • Allkeys-lru:從數(shù)據(jù)集(server.db[i].dict)中挑選最近最少使用的數(shù)據(jù)淘汰腮出;
  • Allkeys-random:從數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰;
  • no-enviction:禁止淘汰數(shù)據(jù)芝薇。

redis怎么自己實(shí)現(xiàn)線程安全的自增胚嘲?

      WATCH mykey
      val = GET mykey
      val = val + 1
      MULTI
      SET mykey $val
      EXEC

通過watch命令來對一個(gè)變量進(jìn)行監(jiān)測。如果一個(gè)變量已經(jīng)被監(jiān)測洛二,當(dāng)變量被修改馋劈,之后的事務(wù)就不會執(zhí)行攻锰。

redis cluster

slot(槽)

redis cluster中有16384個(gè)slot。正常工作的時(shí)候侣滩,每個(gè)Master節(jié)點(diǎn)都負(fù)責(zé)一部分slot口注,當(dāng)有某個(gè)key被映射到某個(gè)Master負(fù)責(zé)的槽,那么這個(gè)Master負(fù)責(zé)為這個(gè)key提供服務(wù)君珠,至于哪個(gè)Master節(jié)點(diǎn)負(fù)責(zé)哪個(gè)槽寝志,這是可以由用戶指定的。只有Master才擁有槽的所有權(quán)策添,如果是某個(gè)Master的slave材部,這個(gè)slave只負(fù)責(zé)槽的使用,但是沒有所有權(quán)唯竹。

連接節(jié)點(diǎn)

CLUSTER MEET命令:用來連接不同的開啟集群支持的Redis節(jié)點(diǎn)乐导。

過程:

  • 如果A節(jié)點(diǎn)接收到meet命令,首先對ip和port進(jìn)行合理性檢查浸颓,然后遍歷nodes物臂,通過判斷對應(yīng)的node是不是處于CLUSTER_NODE_HANDSHAKE狀態(tài),是的話产上,說明是重復(fù)meet棵磷。否則,創(chuàng)建一個(gè)帶HANDSHAKE和MEET標(biāo)記的clusterNode節(jié)點(diǎn)晋涣,添加到nodes中仪媒。
  • A節(jié)點(diǎn)通過定時(shí)任務(wù)遍歷nodes,通過判斷node的link是否為null谢鹊,尋找到之前meet命令添加的節(jié)點(diǎn)算吩,向B節(jié)點(diǎn)發(fā)送一個(gè)meet消息。
  • 節(jié)點(diǎn)B在接收到節(jié)點(diǎn)A發(fā)送的meet消息佃扼,會將節(jié)點(diǎn)A的信息創(chuàng)建一個(gè)node偎巢,添加到節(jié)點(diǎn)B的nodes中,并向節(jié)點(diǎn)A回復(fù)一個(gè)PONG消息松嘶。
  • 節(jié)點(diǎn)A收到節(jié)點(diǎn)B的PONG消息后艘狭,會更新nodes中節(jié)點(diǎn)B的信息,消除HANDSHAKE標(biāo)記翠订。
  • 同樣巢音,節(jié)點(diǎn)B在做定時(shí)任務(wù)的時(shí)候,發(fā)現(xiàn)節(jié)點(diǎn)A的link為null尽超,由于沒有meet flag官撼,會向A發(fā)送PING命令。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末似谁,一起剝皮案震驚了整個(gè)濱河市傲绣,隨后出現(xiàn)的幾起案子掠哥,更是在濱河造成了極大的恐慌,老刑警劉巖秃诵,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件续搀,死亡現(xiàn)場離奇詭異,居然都是意外死亡菠净,警方通過查閱死者的電腦和手機(jī)禁舷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毅往,“玉大人牵咙,你說我怎么就攤上這事∨饰ǎ” “怎么了洁桌?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侯嘀。 經(jīng)常有香客問我另凌,道長,這世上最難降的妖魔是什么戒幔? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任途茫,我火速辦了婚禮,結(jié)果婚禮上溪食,老公的妹妹穿的比我還像新娘。我一直安慰自己娜扇,他們只是感情好错沃,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雀瓢,像睡著了一般枢析。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刃麸,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天醒叁,我揣著相機(jī)與錄音,去河邊找鬼泊业。 笑死把沼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吁伺。 我是一名探鬼主播饮睬,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼篮奄!你這毒婦竟也來了捆愁?” 一聲冷哼從身側(cè)響起割去,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昼丑,沒想到半個(gè)月后呻逆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菩帝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年咖城,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胁附。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酒繁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出控妻,到底是詐尸還是另有隱情州袒,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布弓候,位于F島的核電站郎哭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏菇存。R本人自食惡果不足惜夸研,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望依鸥。 院中可真熱鬧亥至,春花似錦、人聲如沸贱迟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衣吠。三九已至茶敏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缚俏,已是汗流浹背惊搏。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忧换,地道東北人恬惯。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像亚茬,于是被迫代替她去往敵國和親宿崭。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容