redis
后續(xù)源碼文件名稱統(tǒng)一通過()表示,redis底層是C語言坚冀,因此.h、.c文件可認(rèn)為是源碼文件
源碼版本 redis-6.0.5
redis全稱:REmote DIctionary Service 譯為遠(yuǎn)程字典服務(wù)
每個KV鍵值對都存儲在dictEntry(dict.h)里面惊畏,redis底層是哈希表(hashTable)舀透,結(jié)構(gòu)體現(xiàn)在dictEntry是數(shù)組舌稀,*next指針維護(hù)鏈表旱捧。
key是字符串結(jié)構(gòu)塞颁,redis采用sds結(jié)構(gòu)(sds.h)存儲浪讳,由于底層是C語言編寫,C語言沒有String結(jié)構(gòu)惑芭。
sds與char[]的區(qū)別:
- sds長度存儲在len屬性當(dāng)中坠狡,無需再計(jì)算
- 內(nèi)存分配不足導(dǎo)致溢出,sds會提前檢查空間剩余量并進(jìn)行分配
- 減少內(nèi)存分配次數(shù)强衡,sds修改后len變?yōu)?0字節(jié)擦秽,而buf數(shù)組實(shí)際長度為21,10字節(jié)空余漩勤,1字節(jié)用于存儲空字符串
- 二進(jìn)制安全問題:C語言通過空字符串識別結(jié)束感挥,像視頻、圖片越败、音頻等中間內(nèi)容包括了空字符触幼,會導(dǎo)致解析失敗
value存儲在redisObject當(dāng)中(server.h)
對象類型可以根據(jù)命令:type key查看
基本數(shù)據(jù)結(jié)構(gòu)
String
基本介紹:
字符串類型的內(nèi)部編碼(對應(yīng)redisObject中encoding存儲的值)
可通過命令object encoding key查詢編碼
- int:(8字節(jié) 64位)
- embstr:sds的一種格式,存儲小于44字節(jié)的字符串 究飞,redisObject和sds連續(xù)分配置谦,修改時需要重新全部分配,因此設(shè)置為只讀
- raw:存儲大于44字節(jié)的字符串亿傅,redisObject和sds分別分配媒峡。
embstr以及raw的臨界值可通過配置#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44實(shí)現(xiàn)(object.h)超過范圍則自動轉(zhuǎn)換類型,修改數(shù)據(jù)會轉(zhuǎn)換成raw類型葵擎,大內(nèi)存編碼無法退化為小內(nèi)存編碼谅阿。
應(yīng)用場景:
- 熱點(diǎn)內(nèi)容緩存
- 分布式session
- 分布式鎖:setnx
- 全局id:incrby 項(xiàng)目上應(yīng)用:全局msgId
- 原子性操作可應(yīng)用的場景:限流、計(jì)數(shù)
Hash
value只能是字符串類型
基本介紹:
- 優(yōu)點(diǎn):減少內(nèi)存空間、減少key沖突签餐、批量獲取減少IO
- 缺點(diǎn):field無法單獨(dú)設(shè)置過期時間寓涨、無bit操作、數(shù)據(jù)量分布問題(都分布在key所在節(jié)點(diǎn))
- 基本操作指令:hset氯檐、hmset戒良、hscan
實(shí)現(xiàn)原理:(底層由兩種數(shù)據(jù)結(jié)構(gòu)組成)
hash的底層由兩種結(jié)構(gòu)組成:ziplist和hashtable
-
ziplist壓縮列表(ziplist.c):
通過當(dāng)前節(jié)點(diǎn)的長度和上一個節(jié)點(diǎn)的長度計(jì)算出上一個節(jié)點(diǎn)的地址
使用場景:hash鍵值都小于64byte、鍵值對數(shù)量小于512個
可通過redis.conf配置轉(zhuǎn)成哈希表的臨界值:hash-max-ziplist-value冠摄、hash-max-ziplist-entries
當(dāng)超過這兩個閾值的時候轉(zhuǎn)換為hashtable(哈希表)
編碼格式:根據(jù)字節(jié)區(qū)分
-
hashtable哈希表(dict.h):redis底層哈希表可參照此結(jié)構(gòu)
根據(jù)負(fù)載因子就是鏈表的長度(dict_force_resize_ratio=5)糯崎,若大于,則觸發(fā)rehash耗拓,擴(kuò)容大小為當(dāng)前庫大小*2
rehash過程: redis-rehash過程是采用漸進(jìn)式rehash即分多次拇颅、漸進(jìn)式完成的
- 擴(kuò)容大小h[1]為h[0]使用的數(shù)量*2,講rehashidex索引計(jì)數(shù)器置0乔询,開始rehash
- 程序進(jìn)行crud的過程中外,還遷移rehashidex上的節(jié)點(diǎn)韵洋,重新計(jì)算hash值竿刁,遷移h[0]節(jié)點(diǎn)到h[1]當(dāng)中,rehashidx+1
- rud操作(即除了新增操作)會兩個哈希表同時操作搪缨,新增操作只操作h[1]表食拜,保證h[0]中的數(shù)據(jù)只減不增,最后變成空表釋放空間
應(yīng)用場景:
- 用戶的任務(wù)進(jìn)度:key-用戶id field:任務(wù)名稱 value:任務(wù)進(jìn)度
- 用戶的購物車:key-用戶id field:商品 value:商品數(shù)量
List
左右都可取出數(shù)據(jù)
實(shí)現(xiàn)原理:
3.2版本之后采用quicklist來存儲
應(yīng)用場景:
- 由于list是有序排列副编,因此可以作為時間線
- 消息隊(duì)列:BLPOP/BRPOP指令负甸,阻塞等待,有數(shù)據(jù)才彈出
Set
基本介紹:無序集合(最大存儲40億數(shù)據(jù))
實(shí)現(xiàn)原理:根據(jù)數(shù)據(jù)類型用不同的數(shù)據(jù)結(jié)構(gòu)
- 整數(shù)類型:inset存儲
- 非整數(shù)類型:hashtable
應(yīng)用場景:
- 漂流瓶等從集合隨機(jī)抽取的活動
- 點(diǎn)贊痹届、簽到呻待、喜歡的用戶等:key-like+uid value-對象id
- 商品標(biāo)簽:通過交集并集
Zset
基本介紹:有序集合
實(shí)現(xiàn)原理:源碼結(jié)構(gòu)(server.h)
- 元素?cái)?shù)量小于128,長度小于64字節(jié)用ziplist
- 超過閾值后队腐,用skiplist+dict存儲(跳躍表):跳躍表就是維護(hù)了多層數(shù)據(jù)蚕捉,根據(jù)當(dāng)前層判斷是否需要到下層查找
應(yīng)用場景:key score field
- score為時間戳,可以統(tǒng)計(jì)指定時間段內(nèi)的數(shù)據(jù)
- zrevrange:獲取排名
Bitmaps
基本介紹:位運(yùn)算柴淘,8位2進(jìn)制組成
常用指令:bitcount k1 統(tǒng)計(jì)二進(jìn)制位中1的個數(shù)
應(yīng)用場景:
- 用戶訪問統(tǒng)計(jì):位運(yùn)算
- 在線用戶統(tǒng)計(jì):維護(hù)串很長的二進(jìn)制迫淹,用戶根據(jù)id,在線就修改指定位置為1为严,統(tǒng)計(jì)可通過bitcount
Hyperloglogs
基本介紹:位運(yùn)算敛熬,8位2進(jìn)制組成
基本原理:與布隆過濾器有類似作用
應(yīng)用場景:海量數(shù)據(jù)統(tǒng)計(jì)問題
Streams
基本介紹:原理類似kafka
應(yīng)用場景:可實(shí)現(xiàn)發(fā)布訂閱功能