日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Redis 笔记(04)— list类型(作为消息队列使用、在列表头部添加元素、尾部删除元素、查看列表长度、遍历指定列表区间元素、获取指定区间列表元素、阻塞式获取列表元素)

發(fā)布時間:2023/11/28 生活经验 21 豆豆

Redis 的列表是鏈表而不是數(shù)組。這意味著 list 的插入和刪除操作非常快,時間復(fù)雜度為 O(1),但是索引定位很慢,時間復(fù)雜度為 O(n)

當(dāng)列表彈出了最后一個元素之后,該數(shù)據(jù)結(jié)構(gòu)自動被刪除,內(nèi)存被回收。

Redis 的列表結(jié)構(gòu)常用來做異步隊(duì)列使用。將需要延后處理的任務(wù)結(jié)構(gòu)體序列化成字符串塞進(jìn) Redis 的列表,另一個線程從這個列表中輪詢數(shù)據(jù)進(jìn)行處理。

Redis 在列表元素較少的情況下會使用一塊連續(xù)的內(nèi)存來存儲列表,這個結(jié)構(gòu)是 ziplist ,也即是壓縮列表。它將所有的元素緊挨著一起存儲,分配的是一塊連續(xù)的內(nèi)存。當(dāng)數(shù)據(jù)量比較多的時候才會改成 quicklist

因?yàn)槠胀ǖ逆湵硇枰母郊又羔樋臻g太大,會比較浪費(fèi)空間,而且會加重內(nèi)存的碎片化。比如這個列表里存的只是 int 類型的數(shù)據(jù),結(jié)構(gòu)上還需要兩個額外的指針 prevnext 。所以 Redis 將鏈表和 ziplist 結(jié)合起來組成了 quicklist。也就是將多個 ziplist 使用雙向指針串起來使用。這樣既滿足了快速的插入刪除性能,又不會出現(xiàn)太大的空間冗余。

1. list 類型相關(guān)命令

命令說明
lpush key string在key對應(yīng)list的頭部添加字符串元素
rpop key在list的尾部刪除元素,并返回刪除元素
rpush key string在key對應(yīng)list的尾部添加字符串元素
lpop key在list的頭部刪除元素,并返回刪除元素
lset key index value將列表key下標(biāo)為index的元素值設(shè)置為value
llen key返回對應(yīng)list的長度
lrange key start end返回指定區(qū)間內(nèi)的元素,從下標(biāo) 0 開始
ltrim key start end截取list, 保留指定區(qū)間內(nèi)元素
lindex key 下標(biāo)獲取列表下標(biāo)對應(yīng)的指定元素
blpop key[key…] time out刪除,并獲得該列的第一元素, 或阻塞,直到有一個可用
brpop key[key…] time out刪除, 并獲得該列的最后一個元素, 或阻塞,直到有一個可用
rpoplpush source destination刪除列表中的最后一個元素,將其追加到另一個列表
brpoplpush source destination timeout彈出一個列表的值,將他推到另一個列表,并返回他,直到有一個可用

2. 使用示例

127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> lpush list 2
(integer) 2
127.0.0.1:6379> lpush list 3
(integer) 3
127.0.0.1:6379> lpush list 4
(integer) 4
127.0.0.1:6379> lpush list 5
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lpop list
"5"
127.0.0.1:6379> rpop list
"1"
127.0.0.1:6379> lrange list 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> rpush list 1
(integer) 4
127.0.0.1:6379> rpush list -1
(integer) 5
127.0.0.1:6379> rpush list -2
(integer) 6
127.0.0.1:6379> lrange list 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "-1"
6) "-2"
127.0.0.1:6379> lset list 0 00
OK
127.0.0.1:6379> lrange list 0 -1
1) "00"
2) "3"
3) "2"
4) "1"
5) "-1"
6) "-2"
127.0.0.1:6379> llen list
(integer) 6

lindex 需要對鏈表進(jìn)行遍歷,性能隨著參數(shù) index 增大而變差。

127.0.0.1:6379> lindex -2
(error) ERR wrong number of arguments for 'lindex' command
127.0.0.1:6379> lindex list -2
"-1"
127.0.0.1:6379> lindex list 0
"00"

ltrim 和字面上的含義不太一樣,個人覺得它叫 lretain (保留) 更合適一些,因?yàn)?ltrim 跟的兩個參數(shù)start_indexend_index 定義了一個區(qū)間,在這個區(qū)間內(nèi)的值,ltrim 要保留,區(qū)間之外統(tǒng)統(tǒng)砍掉。我們可以通過 ltrim 來實(shí)現(xiàn)一個定長的鏈表,這一點(diǎn)非常有用。

index 可以為負(fù)數(shù),index=-1 表示倒數(shù)第一個元素,同樣 index=-2 表示倒數(shù)第二個元素。

127.0.0.1:6379> ltrim list 1 4
OK
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
4) "-1"
127.0.0.1:6379> blpop list 3
1) "list"
2) "3"
127.0.0.1:6379> brpop list 2
1) "list"
2) "-1"
127.0.0.1:6379> 

3. 消息隊(duì)列

Redislist(列表) 數(shù)據(jù)結(jié)構(gòu)常用來作為異步消息隊(duì)列使用,使用 rpush/lpush 操作入隊(duì)列,使用 lpoprpop 來出隊(duì)列。

lpushrpop 命令可以實(shí)現(xiàn)隊(duì)列功能,只需要生產(chǎn)者將任務(wù)使用 lpush 命令加入到某個鍵中,而消費(fèi)者使用 rpop 命令將任務(wù)從對應(yīng)的鍵中取出來即可。

brpop 命令和 rpop 命令相似,區(qū)別在于 brpop 是阻塞式的,當(dāng)隊(duì)列中沒有任務(wù)時,brpop 命令會一直阻塞住連接,直到隊(duì)列中有任務(wù)。

brpop 命令格式

brpop key seconds

seconds 為 0 表示不限制等待時間,即永遠(yuǎn)阻塞下去。

3.1 隊(duì)列空情況

客戶端是通過隊(duì)列的 pop 操作來獲取消息,然后進(jìn)行處理。處理完了再接著獲取消息,再進(jìn)行處理。如此循環(huán)往復(fù),這便是作為隊(duì)列消費(fèi)者的客戶端的生命周期。

如果隊(duì)列空了,客戶端就會陷入 pop 的死循環(huán),不停地 pop,沒有數(shù)據(jù),接著再 pop,又沒有數(shù)據(jù)。這就是浪費(fèi)生命的空輪詢。空輪詢不但拉高了客戶端的 CPURedisQPS 也會被拉高。

通常我們使用 sleep 來解決這個問題,讓線程睡一會,睡個 1s 鐘就可以了。不但客戶端的 CPU 能降下來,RedisQPS 也降下來了。

time.sleep(1)  # python 睡 1s

3.2 阻塞隊(duì)列

用上面睡眠的辦法可以解決問題。但是有個小問題,那就是睡眠會導(dǎo)致消息的延遲增大。更好的解決方法是使用 blpop/brpop,這兩個指令的前綴字符 b 代表的是 blocking ,也就是阻塞讀。

阻塞讀在隊(duì)列沒有數(shù)據(jù)的時候,會立即進(jìn)入休眠狀態(tài),一旦數(shù)據(jù)到來,則立刻醒過來。消息的延遲幾乎為零。用 blpop/brpop 替代前面的 lpop/rpop 可以完美解決隊(duì)列延遲問題。

3.3 空閑連接自動斷開

如果線程一直阻塞在哪里,Redis 的客戶端連接就成了閑置連接,閑置過久,服務(wù)器一般會主動斷開連接,減少閑置資源占用。這個時候 blpop/brpop 會拋出異常來。

所以編寫客戶端消費(fèi)者的時候要小心,注意捕獲異常,還要重試。

代碼參考:
玩轉(zhuǎn) Redis:簡單消息隊(duì)列

玩轉(zhuǎn) Redis — 延時消息隊(duì)列

總結(jié)

以上是生活随笔為你收集整理的Redis 笔记(04)— list类型(作为消息队列使用、在列表头部添加元素、尾部删除元素、查看列表长度、遍历指定列表区间元素、获取指定区间列表元素、阻塞式获取列表元素)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。