Redis如何解決BigKey
一 面試題引入
- 阿里廣告平臺(tái),海量數(shù)據(jù)里查詢某一固定前綴的key。
- 小紅書(shū),你如何在生產(chǎn)上限制keys * / flushdb / flushall等危險(xiǎn)命令以防止誤刪誤用?
- 美團(tuán):MEMORY USAGE 命令你用過(guò)嗎?
- BigKey 問(wèn)題,多大算big,如何發(fā)現(xiàn),如何刪除,如何處理?
- BigKey 你做過(guò)調(diào)優(yōu)嗎?惰性釋放lazyfree了解過(guò)嗎?
- Morekey問(wèn)題,生產(chǎn)上redis數(shù)據(jù)庫(kù)有1000W記錄,該如何遍歷?key*可以嗎?
二 MoreKey案例
2.1 大批量往redis里面插入2000W測(cè)試數(shù)據(jù)key
2.1.1 Linux Bash下執(zhí)行,插入100W
for((i=1;i<=100*10000;i++)); do echo "set K$i V$i" >> /tmp/redisTest.txt ; done;
2.1.2 通過(guò)redis提供的管道 --pipe命令插入100W大批量數(shù)據(jù)
cat /tmp/redisTest.txt | /opt/redis-7.0.0/src/redis-cli -h 127.0.0.1 -p 6379 -a 111111 --pipe
2.2 key *
key * 這個(gè)指令有致命的弊端,在實(shí)際環(huán)境中最好不要使用
這個(gè)指令沒(méi)有offset、limit參數(shù),是要一次性吐出所有滿足條件的key,由于redis是單線程的,其所有操作都是原子的,而keys算法是遍歷算法,復(fù)雜度是O(n),如果實(shí)例中有千萬(wàn)級(jí)以上的key,這個(gè)指令就會(huì)導(dǎo)致Redis服務(wù)卡頓,所有讀寫(xiě)Redis的其它的指令都會(huì)被延后甚至?xí)瑫r(shí)報(bào)錯(cuò),可能會(huì)引起緩存雪崩甚至數(shù)據(jù)庫(kù)宕機(jī)。
2.3 生產(chǎn)上如何限制keys*/flushdb/flushall等危險(xiǎn)命令以防止誤刪誤用?
通過(guò)配置設(shè)置禁用這些命令,redis.conf在SECURITY這一項(xiàng)中:

2.4 不用keys * 不滿卡頓,那該用什么?
2.4.1 scan命令
類(lèi)似mysql limit ,但不完全相同。
Redis SCAN命令及其相關(guān)命令 SSCAN,HSCAN,ZSCAN命令都是用于增量遍歷集合中的元素。
- SCAN:用于迭代當(dāng)前數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù)鍵
- SSCAN:用于迭代集合鍵中的元素
- HSCAN:用于迭代哈希鍵中的鍵值對(duì)
- ZSCAN:用于迭代有序集合中的元素(包括元素成員和元素分值)
2.4.2 scan命令用于迭代數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù)鍵
redis SCAN 命令基本語(yǔ)法如下:
SCAN cousor [MATCH pattern] [COUNT count]
- cursor:游標(biāo)
- pattern:匹配的模式
- count:指定從數(shù)據(jù)集里返回多少元素,默認(rèn)值是10

基于游標(biāo)的迭代器,需要基于上一次的游標(biāo)延續(xù)之前的迭代過(guò)程以0作為游標(biāo)開(kāi)始一次新的迭代,直到命令返回游標(biāo)0完成一次遍歷,不保證每次執(zhí)行都返回某個(gè)給定數(shù)量的元素,支持模糊查詢。一次返回的數(shù)量不可控,只能是大概率符合count參數(shù)。
- SCAN命令是一個(gè)基于游標(biāo)的迭代器,每次被調(diào)用之后,都會(huì)想用戶返回一個(gè)新的游標(biāo),用戶在下次迭代時(shí)需要使用這個(gè)新游標(biāo)作為SCAN命令的游標(biāo)參數(shù),以此來(lái)延續(xù)之前的迭代過(guò)程。
- SCAN返回一個(gè)包含兩個(gè)元素的數(shù)組
- 第一個(gè)元素:用于進(jìn)行下一次迭代的新游標(biāo)
- 第二個(gè)元素:是一個(gè)數(shù)組,這個(gè)數(shù)組中包含了所有被迭代的元素。如果新游標(biāo)返回零表示迭代已結(jié)束。
SCAN的遍歷順序:非常特別,它不是從第一維數(shù)組的第零位一直遍歷到末尾,而是采用了高位進(jìn)位加法來(lái)遍歷,之所以使用這樣特殊的方式進(jìn)行遍歷,是考慮到字典的擴(kuò)容和縮容時(shí)避免槽位的遍歷重復(fù)和遺漏。
三 BigKey
3.1 多大算Big
- 阿里云Redis開(kāi)發(fā)規(guī)范:
拒絕bigkey(防止網(wǎng)卡流量,慢查詢)
string類(lèi)型控制在10KB以內(nèi),hash、list、set、zset元素個(gè)數(shù)不要超過(guò)5000。
非字符串的bigkey,不要使用del刪除,使用hscan、sscan、zscan方式漸進(jìn)式刪除,同時(shí)要注意防止bigkey過(guò)期時(shí)間自動(dòng)刪除問(wèn)題(例如一個(gè)200萬(wàn)的zset設(shè)置1小時(shí)過(guò)期,會(huì)觸發(fā)del操作,造成阻塞,而且該操作不會(huì)出現(xiàn)在慢查詢中(latency可查))。
- string和二級(jí)結(jié)構(gòu)
- string是value,最大512MB 但是大于10KB就是bigkey。
- list/hash/set和zset,個(gè)數(shù)超過(guò)5000就是bigkey

3.2 bigkey的危害
- 內(nèi)存不均,集群遷移困難
- 超時(shí)刪除,大key刪除作梗
- 網(wǎng)絡(luò)流量阻塞
3.3 如何產(chǎn)生
- 社交類(lèi):典型案例粉絲逐步遞增
- 匯總統(tǒng)計(jì):某個(gè)報(bào)表,月日年的積累
3.4 如何發(fā)現(xiàn)
redis-cli --bigkeys
- 好處:給出每種數(shù)據(jù)結(jié)構(gòu)Top 1 bigkey,同時(shí)給出每種數(shù)據(jù)類(lèi)型的鍵值個(gè)數(shù) + 平均大小
- 不足:想查詢大于10KB的所有key,–bigkeys參數(shù)就無(wú)能為力了。
需要用到memory usage來(lái)計(jì)算每個(gè)鍵值的字節(jié)數(shù)


MOMROY USAGE :給出一個(gè)key和它的值在RAM中所占用的字節(jié)數(shù)(計(jì)算每個(gè)鍵值的字節(jié)數(shù))。
3.5 如何刪除
非字符串的bigkey,不要使用del刪除,使用hscan、sscan、zscan方式漸進(jìn)式刪除。
- string:一般用del,如果過(guò)于龐大使用unlink
- hash:使用hscan每次獲取少量field-value,再使用hdel刪除每個(gè)field

list:使用ltrim漸進(jìn)式逐步刪除,直到全部刪除完成。
Ltrim對(duì)一個(gè)列表進(jìn)行修剪(trim),就是說(shuō),讓列表只保留指定區(qū)域內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除。下標(biāo)0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類(lèi)推。也可以使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類(lèi)推。
語(yǔ)法:LTRIM key_NAME START STOP

set:使用sscan每次獲取部分元素,再使用srem命令刪除每個(gè)元素

zset:使用zscan每次獲取部分元素,再使用ZREMRANGEBYRANK命令刪除每個(gè)元素

四 BigKey生產(chǎn)調(diào)優(yōu)
在redis.conf配置文件LAZY FREEING相關(guān)說(shuō)明:


到此這篇關(guān)于Redis如何解決BigKey的文章就介紹到這了,更多相關(guān)Redis BigKey內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文詳解Redis在Ubuntu系統(tǒng)上的安裝步驟
安裝redis在Ubuntu上有多種方法,下面這篇文章主要給大家介紹了關(guān)于Redis在Ubuntu系統(tǒng)上安裝的相關(guān)資料,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
Redis教程(四):Hashes數(shù)據(jù)類(lèi)型
這篇文章主要介紹了Redis教程(四):Hashes數(shù)據(jù)類(lèi)型,本文講解了Hashes數(shù)據(jù)類(lèi)型概述、相關(guān)命令列表和命令使用示例等內(nèi)容,需要的朋友可以參考下2015-04-04
詳解redis分布式鎖(優(yōu)化redis分布式鎖的過(guò)程及Redisson使用)
在分布式的開(kāi)發(fā)中,以電商庫(kù)存的更新功能進(jìn)行講解,在實(shí)際的應(yīng)用中相同功能的消費(fèi)者是有多個(gè)的,這篇文章主要介紹了redis分布式鎖詳解(優(yōu)化redis分布式鎖的過(guò)程及Redisson使用),需要的朋友可以參考下2021-11-11
Redis分布式鎖與Redlock算法實(shí)現(xiàn)
在Redis中,可以使用多種方式實(shí)現(xiàn)分布式鎖,如使用SETNX命令或RedLock算法,本文就來(lái)介紹一下Redis分布式鎖與Redlock算法實(shí)現(xiàn),感興趣的可以了解一下2023-12-12
基于redis實(shí)現(xiàn)token驗(yàn)證用戶是否登陸
這篇文章主要為大家詳細(xì)介紹了基于redis實(shí)現(xiàn)token驗(yàn)證用戶是否登陸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
Redis內(nèi)存回收和對(duì)象共享的實(shí)現(xiàn)示例
本文主要介紹了Redis內(nèi)存回收和對(duì)象共享的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03

