redis學(xué)習(xí)

最近學(xué)習(xí)了一段時(shí)間的redis钓账,以下是筆記毁渗,歡迎各位大佬們留言評(píng)論灌诅,若有不對(duì)的地方請指出芳来,我會(huì)及時(shí)更正!蟹蟹大家猜拾!

目錄:

1.redis簡介

2.redis豐富的數(shù)據(jù)結(jié)構(gòu)

3.redis事務(wù)即舌、分布式鎖

4.持久化

5.reids存儲(chǔ)使用的數(shù)據(jù)模型

6.redis淘汰策略

7.redis底層數(shù)據(jù)類型介紹


redis簡介

基于內(nèi)存存儲(chǔ)的非關(guān)系型數(shù)據(jù)庫、

性能強(qiáng)勁挎袜、單線程運(yùn)作侥涵、請求入隊(duì)

支持的數(shù)據(jù)結(jié)構(gòu)豐富:string、list宋雏、hash芜飘、set、zset

支持RDB和AOF持久化


redis支持的數(shù)據(jù)結(jié)構(gòu):string

set key value

setnx key value

setex key seconds value

exists key

get key

mget key1 key2 …

mset k1 v1 k2 v2 …

incr key

getset key value

pttl key

.....................................

redis支持的數(shù)據(jù)結(jié)構(gòu):hash

hset key field value

hsetnx key value 如果field存在則不改變

hget key field

hdel key fidle1 field2 …

hlen key 返回字段個(gè)數(shù)

hmget key f1 f2 …

hmset key f1 v1 f2 v2 …

hexists key field

hkeys key

hvals key

hgetall key

hincrby key field

hincrbyfloat key

field

..............................................

Ps:哈希類型的內(nèi)部編碼有ziplist 和 hashtable

當(dāng)哈希元素小于hash-max-ziplist-entries配置磨总、同時(shí)所有值都小于hash-max-ziplist-value配置嗦明,就會(huì)利用ziplist這樣更節(jié)省內(nèi)存?? ?/etc/redis/redis.conf

object encoding key 可以查看數(shù)據(jù)的編碼,我們可以發(fā)現(xiàn)蚪燕,當(dāng)超過上述兩個(gè)配置的值后娶牌,編碼會(huì)發(fā)生改變

redis支持的數(shù)據(jù)結(jié)構(gòu):list

lpush key v1 v2 …

rpush key v1 v2 …

lrange start end 0 -1查找所有

linsert key before/after value

lindex key index -1返回最后一個(gè)

llen key

lpop key

rpopkey?

lremkey count value??

…………………........................

Ps:內(nèi)部編碼有ziplist 和 linkedlist

當(dāng)list元素小于list-max-ziplist-entries配置、同時(shí)所有值都小于list-max-ziplist-value配置馆纳,就會(huì)利用ziplist這樣更節(jié)省內(nèi)存

Redis3.2版本新增了quicklist編碼诗良,以ziplist為節(jié)點(diǎn)的linkedlist,結(jié)合了兩者的優(yōu)勢

redis支持的數(shù)據(jù)結(jié)構(gòu):set

set:無索引鲁驶、無重復(fù)鉴裹、無序

sadd key v1 v2 …

srem key v1 v2 …

scard key 計(jì)算元素個(gè)數(shù)

sismember key element 判斷元素是否在集合中

spop key 隨機(jī)彈出元素

smembers key 返回所有元素

sinter key1 key2 返回兩個(gè)集合交集

sunion key1 key2 返回兩個(gè)集合并集?

sdiff key1 key2 返回兩個(gè)集合差集,順序影響結(jié)果

…………………..................

Ps:內(nèi)部編碼有intset 和 hashtable

當(dāng)set集合元素小于set-max-intset-entries配置默認(rèn)512個(gè)且都是整數(shù)钥弯,就會(huì)利用intset這樣更節(jié)省內(nèi)存径荔,當(dāng)數(shù)量沒有達(dá)到,但是其中只要有一個(gè)元素不是整數(shù)脆霎,編碼都會(huì)變?yōu)閔ashtable

redis支持的數(shù)據(jù)結(jié)構(gòu):zset

zset:元素有分?jǐn)?shù)作為排序依據(jù)总处、無重復(fù)

zadd key score member …

zcard key 計(jì)算成員個(gè)數(shù)

zscore key member 返回這個(gè)成員分?jǐn)?shù)

zrank key member 從低到高返回排名

zrevrank key member 從高到低返回排名,從0開始算的

zrem key member 移除元素

zincrby key increment member 給元素增加分?jǐn)?shù)

zrange key start end 返回排名的成員從低到高?

zrevrange key start end 返回排名的成員反之

zcount key min max 返回指定分?jǐn)?shù)范圍元素個(gè)數(shù)

zremrangebyscore key min max 刪除指定分?jǐn)?shù)范圍成員

…………………..................................

Ps:內(nèi)部編碼有ziplist 和 skiplist

當(dāng)zset集合元素個(gè)數(shù)小于zset-max-ziplist-entries配置默認(rèn)128睛蛛,且每個(gè)元素的值都小于zset-max-ziplist-value默認(rèn)64字節(jié)鹦马,就會(huì)使用ziplist編碼胧谈,否則編碼都會(huì)變?yōu)閟kiplist,因?yàn)槌^設(shè)置值荸频,讀寫效率就會(huì)下降

redis事務(wù)

1.multi 事務(wù)開始

2.一個(gè)事務(wù)需要執(zhí)行的操作第岖,例如多條命令行

3.exec結(jié)束事務(wù);discard取消事務(wù)

redis事務(wù)不支持回滾试溯,只要事務(wù)開始到事務(wù)提交蔑滓,期間只要有命令執(zhí)行成功,就會(huì)改變遇绞,所以redis提供了watch命令解決這個(gè)問題

1.watch key

2.multi

3.命令…

4.exec提交事務(wù)

watch代表監(jiān)聽一個(gè)key键袱,執(zhí)行事務(wù)的時(shí)候如果這個(gè)key發(fā)生了改變,事務(wù)執(zhí)行就不成功摹闽,返回nil蹄咖,這個(gè)時(shí)候需要人工干預(yù)

redis分布式鎖

這些命令是分布式鎖需要用到的命令,具體的流程如圖所示

setnx key value 返回1則代表拿到鎖付鹿,返回0則代表沒有拿到鎖

expire key timeout 為key設(shè)置一個(gè)超時(shí)時(shí)間澜汤,防止出現(xiàn)鎖永遠(yuǎn)不被釋放的情況

del key 釋放鎖

getset key

value


redis持久化

rdb

RDB持久化是把當(dāng)前進(jìn)程數(shù)據(jù)生成快照保存到硬盤的過程,觸發(fā)RDB持久化過程分為手動(dòng)觸發(fā)和自動(dòng)觸發(fā)舵匾。

手動(dòng):save bgsave俊抵,執(zhí)行save命令的時(shí)候會(huì)阻塞redis直到RDB完成為止;bgsave則是fork出子線程完成RDB操作坐梯,不會(huì)阻塞redis徽诲,只是在fork子線程會(huì)阻塞,這個(gè)時(shí)間不會(huì)很長吵血;

自動(dòng):在配置文件中有默認(rèn)save 900 1 save 300 10 save 60 10000谎替,只要滿足這三個(gè)其中的任意一個(gè)都會(huì)執(zhí)行自動(dòng)bgsave;

redis的save m n 是通過serverCron,dirty,lastsave時(shí)間戳來實(shí)現(xiàn)的蹋辅;

serverCron檢查配置文件钱贯、

dirty計(jì)數(shù)器記錄數(shù)據(jù)庫一共執(zhí)行了多少次修改,執(zhí)行bgsave會(huì)置零

lastsave是記錄上次執(zhí)行bgsave的時(shí)間

當(dāng)前時(shí)間-lastsave>m&&dirty>=n

RDB文件載入工作是在服務(wù)器啟動(dòng)時(shí)自動(dòng)執(zhí)行侦另,AOF優(yōu)先級(jí)高于RDB秩命,所以如果要使用RDB就要關(guān)閉AOF,redis載入RDB文件期間淋肾,redis處于阻塞狀態(tài)硫麻,直到載入完成為止;

aof

AOF持久化是將每次redis執(zhí)行的命令記錄起來樊卓,類似于mysqlbinlog,redis重啟時(shí)執(zhí)行aof文件中的命令來恢復(fù)數(shù)據(jù)

配置文件開啟appendonly yes 杠河,aof是自動(dòng)記錄碌尔,aof執(zhí)行流程浇辜;

1.命令追加:將命令追加到緩沖區(qū)aof_buf,這是為了避免磁盤io導(dǎo)致性能降低唾戚;

2.文件寫入和文件同步:緩沖區(qū)的文件同步策略參數(shù)由appendfsync控制

Everysec柳洋,默認(rèn),每次的命令都寫入aof文件中叹坦,但是每秒執(zhí)行一次文件同步操作熊镣;

Always:每次的命令寫入aof文件中,并且執(zhí)行文件同步操作募书,速度最慢但是最安全绪囱;

No:每次命令寫入aof文件中,但是由操作系統(tǒng)決定何時(shí)執(zhí)行文件同步莹捡,速度最快但是不安全鬼吵;?

3.文件重寫:子線程執(zhí)行,不影響主線程篮赢,目的主要是消除重復(fù)命令齿椅,過期的數(shù)據(jù),減少aof文件的大衅羝涣脚;

redis數(shù)據(jù)模型

涉及到內(nèi)存分配器(如jemalloc)、簡單動(dòng)態(tài)字符串(SDS)寥茫、5種對(duì)象類型及內(nèi)部編碼涩澡、redisObject。

下圖是執(zhí)行set hello world時(shí)坠敷,涉及到的數(shù)據(jù)模型

dictEntry:每個(gè)鍵值對(duì)都會(huì)有一個(gè)dictEntry妙同,里面存儲(chǔ)了指向key和value的指針,next指向下一個(gè)dictEntry膝迎;

Key:并不是直接存儲(chǔ)hello粥帚,而是存儲(chǔ)在sds結(jié)構(gòu)中;

Value:redisObject限次,redis支持的五種數(shù)據(jù)類型都是通過redisObject來存儲(chǔ)的芒涡,type代表類型,ptr指向?qū)ο笏诘刂仿袈址愋偷闹惦m然通過redisObject包裝费尽,但是仍然通過sds來存儲(chǔ);


Jemalloc:redis內(nèi)存分配器有三種羊始,libc旱幼、jemalloc、tcmalloc突委,默認(rèn)是jemalloc柏卤,在64位系統(tǒng)中冬三,將內(nèi)存分為,小缘缚,大勾笆,巨大三個(gè)級(jí)別,每個(gè)級(jí)別又有很多區(qū)域桥滨,redis存儲(chǔ)數(shù)據(jù)時(shí)窝爪,會(huì)找最合適的區(qū)域來存儲(chǔ);

RedisObject:類似于這樣的屬性RedisObject(type, lru, redis, refcount, encoding)

type齐媒,表示對(duì)象的類型蒲每,也就是redis支持的數(shù)據(jù)結(jié)構(gòu),占4個(gè)比特里初;

encoding啃勉,表示對(duì)象的內(nèi)部編碼,占4個(gè)比特双妨;

lru淮阐,記錄了對(duì)象最后一次被命令訪問的時(shí)間,對(duì)比這個(gè)時(shí)間和當(dāng)前時(shí)間可以得出這個(gè)對(duì)象的空轉(zhuǎn)刁品,從而在redis內(nèi)存回收機(jī)制是-lru的時(shí)候泣特,會(huì)優(yōu)先選擇空轉(zhuǎn)時(shí)間最長的對(duì)象進(jìn)行釋放,4.0版本占24比特挑随,2.6版本占22比特状您;

refcount,表示該對(duì)象被引用的次數(shù)兜挨,整型膏孟,初始化系對(duì)象為1,被新的調(diào)用拌汇,+1柒桑,當(dāng)對(duì)象不再被新的調(diào)用,-1噪舀,如果為0魁淳,則釋放該對(duì)象,refcount>1被稱為共享對(duì)象与倡,因?yàn)槌霈F(xiàn)重復(fù)的對(duì)象界逛,redis不會(huì)重復(fù)創(chuàng)建;

ptr纺座,指向具體的數(shù)據(jù)息拜,比如字符串就指向sds;

SDS:簡單動(dòng)態(tài)字符串(simple dynamic string),SDS(len, free, buf)

Len:表示buf已經(jīng)使用的長度

Free:表示buf未使用的長度

Buf:字節(jié)數(shù)組

與C字符串類似的是该溯,buf也是以’\0’作為結(jié)尾岛抄;

redis淘汰策略

noeviction: 不刪除策略, 達(dá)到最大內(nèi)存限制時(shí), 如果需要更多內(nèi)存, 直接返回錯(cuò)誤信息别惦。

allkeys-lru: 所有key通用; 優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key狈茉。

volatile-lru: 只限于設(shè)置了?expire?的部分; 優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key。

allkeys-random: 所有key通用; 隨機(jī)刪除一部分 key掸掸。volatile-random: 只限于設(shè)置了?expire?的部分; 隨機(jī)刪除一部分 key氯庆。

volatile-ttl: 只限于設(shè)置了?expire?的部分; 優(yōu)先刪除剩余時(shí)間(time to live,TTL) 短的key。

redis簡單正則查詢key

合理的運(yùn)用一些正則符號(hào)扰付,比如? *? ?? []??? 減少去全量查找產(chǎn)生的內(nèi)存開銷

keys hell* 可以查到到比如 hello helloo?? *代表一位或者多位

keys hell? 可以查找到比如 hello hella???? ?代表一位

keys hel[lo]o可以查到hello heloo???? []里面填的什么內(nèi)容就會(huì)在這個(gè)數(shù)組里面匹配堤撵,里面也可以放正則表達(dá)式,比如[a-zA-Z]

redis數(shù)據(jù)類型詳解

linkedList:

linkedList:雙向列表的每個(gè)數(shù)據(jù)節(jié)點(diǎn)都有兩個(gè)指針羽莺,分別指向前面一個(gè)節(jié)點(diǎn)和后一個(gè)節(jié)點(diǎn)实昨,因此從雙向列表中的每一個(gè)節(jié)點(diǎn)都很容易獲取前一個(gè)節(jié)點(diǎn)和后一個(gè)節(jié)點(diǎn);

這個(gè)是linkedList的數(shù)據(jù)結(jié)構(gòu)


特點(diǎn):訪問快速盐固,從頭部或者尾部插入元素快荒给,時(shí)間復(fù)雜度為o(1),自帶鏈表長度的屬性刁卜,所以得出鏈表長度的時(shí)間復(fù)雜度為o(1)志电;

zipList:

適用于存儲(chǔ)小的整數(shù)值或者比較簡短的字符串,如果超過redis的配置蛔趴,會(huì)自動(dòng)轉(zhuǎn)換為linkedlist挑辆;

之所以達(dá)到了壓縮的效果,是因?yàn)榇鎯?chǔ)的原理避開了內(nèi)存碎片孝情,它占用的是一大塊內(nèi)存鱼蝉,每一個(gè)entry都是連續(xù)再一起的,而linkedlist是通過指針來指向的箫荡,首先指針會(huì)占內(nèi)存魁亦,內(nèi)存分配器分配內(nèi)存的時(shí)候并不是數(shù)據(jù)多大就分配多大內(nèi)存,而是分配一塊合適這個(gè)數(shù)據(jù)的內(nèi)存空間菲茬,也造成了內(nèi)存浪費(fèi)吉挣;

壓縮的原理:entry里面的prevrawlen屬性會(huì)記錄前一個(gè)entry占用的字節(jié)總數(shù),如果前一個(gè)entry的長度小于254字節(jié)婉弹,那么prevrawlen屬性就會(huì)用1個(gè)字節(jié)的空間保存這個(gè)長度值睬魂,反之上一個(gè)entry大于等于254,就會(huì)用5個(gè)字節(jié)保存這個(gè)值镀赌;

弊端:連鎖更新效應(yīng)氯哮,假設(shè)現(xiàn)在有一個(gè)ziplist,有10個(gè)entry商佛,每個(gè)entry的大小都是253喉钢,那么每個(gè)prevrawlen的都是占用1個(gè)字節(jié)姆打,但是我現(xiàn)在插入了一條255的entry,這個(gè)時(shí)候新entry的后一個(gè)entry的prevrawlen屬性就需要擴(kuò)大肠虽,導(dǎo)致這個(gè)entry的大小變了幔戏,又導(dǎo)致后面的也變了,一直變到最后一個(gè)entry税课,這樣子就一直連續(xù)在做內(nèi)存分配操作闲延,時(shí)間復(fù)雜度大大提升,最壞的情況是o(N^2)

intset:



創(chuàng)建一個(gè)set集合的時(shí)候韩玩,首先會(huì)指定一個(gè)默認(rèn)編碼垒玲,默認(rèn)是INTSET_ENC_INT16

執(zhí)行插入新元素的時(shí)候,會(huì)根據(jù)value得到合適的編碼找颓,然后比較當(dāng)前集合的編碼合愈,如果不滿足就對(duì)集合進(jìn)行升級(jí);

如果滿足击狮,先判斷集合元素是否存在佛析,如果存在就直接返回,如果不存在帘不,擴(kuò)大集合空間说莫,選新的內(nèi)存地址,添加新元素寞焙;

intset內(nèi)部只有”編碼升級(jí)”的過程储狭,沒有”降級(jí)”的操作。當(dāng)將唯一一個(gè)高位元素從將集合移除時(shí)捣郊,此時(shí)辽狈,集合不會(huì)轉(zhuǎn)換為低位編碼集合。

hashtable:


table屬性是一個(gè)數(shù)組呛牲,里面存儲(chǔ)的都是一個(gè)指向dictEntry的指針刮萌,而每個(gè)dictEntry都有一個(gè)next指向下一個(gè)元素的指針屬性,如果出現(xiàn)鍵哈希值相同的情況娘扩,會(huì)被分到同一個(gè)索引上着茸,然后它們通過next就形成了一個(gè)單向鏈表,從而解決了哈希沖突的問題琐旁;

Set應(yīng)用場景:它的特性是無序涮阔,不重復(fù),求交集灰殴、并集敬特、差集很方便;適用于存儲(chǔ)用戶粉絲,計(jì)算共同好友伟阔;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辣之,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子皱炉,更是在濱河造成了極大的恐慌怀估,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娃承,死亡現(xiàn)場離奇詭異奏夫,居然都是意外死亡怕篷,警方通過查閱死者的電腦和手機(jī)历筝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廊谓,“玉大人梳猪,你說我怎么就攤上這事≌舯裕” “怎么了春弥?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叠荠。 經(jīng)常有香客問我匿沛,道長,這世上最難降的妖魔是什么榛鼎? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任逃呼,我火速辦了婚禮,結(jié)果婚禮上者娱,老公的妹妹穿的比我還像新娘抡笼。我一直安慰自己,他們只是感情好黄鳍,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布推姻。 她就那樣靜靜地躺著,像睡著了一般框沟。 火紅的嫁衣襯著肌膚如雪藏古。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天忍燥,我揣著相機(jī)與錄音拧晕,去河邊找鬼。 笑死灾前,一個(gè)胖子當(dāng)著我的面吹牛防症,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼蔫敲,長吁一口氣:“原來是場噩夢啊……” “哼饲嗽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奈嘿,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤貌虾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后裙犹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尽狠,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年叶圃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袄膏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掺冠,死狀恐怖沉馆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情德崭,我是刑警寧澤斥黑,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站眉厨,受9級(jí)特大地震影響锌奴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜憾股,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一鹿蜀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荔燎,春花似錦耻姥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至座享,卻和暖如春婉商,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渣叛。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工丈秩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淳衙。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓蘑秽,卻偏偏與公主長得像饺著,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肠牲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351