欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis Sorted Set類型使用及應(yīng)用場景

 更新時(shí)間:2024年06月12日 11:44:30   作者:Applosl  
Sorted Set是Redis常用的一種是數(shù)據(jù)類型,本文主要介紹了Redis Sorted Set類型使用及應(yīng)用場景,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

sorted set在沒有重復(fù)元素的集合基礎(chǔ)上,每個(gè)元素多了一個(gè)分?jǐn)?shù)score屬性作為權(quán)重,查詢時(shí)可以用score排序。

Sorted Set類型的常用操作

ZADD 添加元素

127.0.0.1:6379> ZADD rank 98 u1
(integer) 1
127.0.0.1:6379> ZADD rank 95 u2
(integer) 1
127.0.0.1:6379> ZADD rank 60 u3
(integer) 1
127.0.0.1:6379> ZADD rank 76 u4
(integer) 1
127.0.0.1:6379> ZADD rank 77 u5
(integer) 1

ZCARD 獲取集合成員數(shù)量

127.0.0.1:6379> ZCARD rank
(integer) 5

ZCOUNT 獲取指定分?jǐn)?shù)段內(nèi)的成員數(shù)量

127.0.0.1:6379> ZCOUNT rank 80 100
(integer) 2

ZINCRBY 給集合中指定成員增加指定分?jǐn)?shù)

127.0.0.1:6379> ZINCRBY rank 2 u3
"62"

ZRANGE/ZREVRANGE 返回按索引排序的成員

127.0.0.1:6379> ZRANGE rank 0 1 # 分?jǐn)?shù)從小到大
1) "u3"
2) "u4"

127.0.0.1:6379> ZREVRANGE rank 0 2 # 分?jǐn)?shù)從大到下
1) "u1"
2) "u2"
3) "u5"

ZRANGEBYSCORE/ZREVRANGEBYSCORE 返回按指定分?jǐn)?shù)段內(nèi)的元素列表

127.0.0.1:6379> ZRANGEBYSCORE rank 80 100 # 分?jǐn)?shù)段從小到大
1) "u2"
2) "u1"

127.0.0.1:6379> ZREVRANGEBYSCORE rank 100 80 # 分?jǐn)?shù)段從大到小
1) "u1"
2) "u2"

ZREM 刪除指定元素

127.0.0.1:6379> ZREM rank u2
(integer) 1

實(shí)際應(yīng)用場景

1.排行榜

實(shí)現(xiàn)一個(gè)實(shí)時(shí)變化的積分排行榜,可以利用 ZREVRANGE 輕松展現(xiàn)最高排名,并實(shí)現(xiàn)分頁查詢
首先將成員名單錄入

127.0.0.1:6379> ZADD rank 0 player1 0 player2 0 player3 0 player4 0 player5 0 player6
(integer) 6

當(dāng)然也可以在合適的時(shí)機(jī)將新增的成員單個(gè)寫入

然后開始實(shí)時(shí)計(jì)算增加的分?jǐn)?shù) 使用ZINCRBY, 增加完后會(huì)直接返回當(dāng)前成員的最終分?jǐn)?shù)

127.0.0.1:6379> ZINCRBY rank 50 player1 
"50"
127.0.0.1:6379> ZINCRBY rank 53 player3 
"53"
127.0.0.1:6379> ZINCRBY rank 20 player5 
"20"
127.0.0.1:6379> ZINCRBY rank 40 player6
"40"
127.0.0.1:6379> ZINCRBY rank 40 player5
"60"
127.0.0.1:6379> ZINCRBY rank -2 player6 # 負(fù)數(shù)也是可以的 相當(dāng)于減分
"38"

也可以不用初始化成員分?jǐn)?shù) 直接給一個(gè)不存在的的成員增加分?jǐn)?shù),默認(rèn)會(huì)創(chuàng)建并增加分?jǐn)?shù),默認(rèn)從0開始

127.0.0.1:6379> ZINCRBY rank 55 player7
"55"

最后獲取排行榜上前3的成員,使用ZREVRANGE

127.0.0.1:6379> ZREVRANGE rank 0 2
1) "player5"
2) "player7"
3) "player3"

如果要帶上分?jǐn)?shù),需要增加一個(gè)參數(shù) WITHSCORES

127.0.0.1:6379> ZREVRANGE rank 0 2 WITHSCORES
1) "player5"
2) "60"
3) "player7"
4) "55"
5) "player3"
6) "53"

2.定時(shí)/延遲任務(wù)

定時(shí)/延遲任務(wù),或是延遲隊(duì)列類功能,最重要的是在指定時(shí)間后才開始處理相關(guān)任務(wù)。

以下是大致實(shí)現(xiàn)方式

任務(wù)生產(chǎn)端:

每個(gè)任務(wù)生成一個(gè)任務(wù)ID(要有唯一性),將具體的任務(wù)信息可以放在其他數(shù)據(jù)庫里,當(dāng)然也可以放在Redis里。然后將任務(wù)ID作為sorted set的成員, 需要執(zhí)行任務(wù)時(shí)間點(diǎn)的時(shí)間戳作為score寫入(如果是延遲任務(wù)就計(jì)算出具體的時(shí)間戳)

127.0.0.1:6379> ZADD tasks 1000 t1 # 假設(shè)當(dāng)前時(shí)間戳從1000開始
(integer) 1
127.0.0.1:6379> ZADD tasks 1003 t2  # 3s后才能觸發(fā)的任務(wù)
(integer) 1
127.0.0.1:6379> ZADD tasks 1004 t3
(integer) 1
127.0.0.1:6379> ZADD tasks 1004 t4
(integer) 1

這時(shí)sorted set里的任務(wù)順序大概是這樣(按分?jǐn)?shù)從小達(dá)到)

t1t2t3t4
1000100310041004

任務(wù)消費(fèi)端

啟動(dòng)一個(gè)進(jìn)程循環(huán)獲取任務(wù), 獲取分?jǐn)?shù)的范圍在當(dāng)前時(shí)間戳之前(表示已經(jīng)到期的任務(wù))

127.0.0.1:6379> ZRANGEBYSCORE tasks -inf 1000
1) "t1"

程序代碼大概可以這樣寫

# 偽代碼
while true {
	nowTimestamp = time.now() # 獲取當(dāng)前時(shí)間戳
	taskIds = redis.ZRANGEBYSCORE("tasks", "-inf", nowTimestamp)
	for taskId in TaskIds {
		# TODO 執(zhí)行任務(wù)處理邏輯
	}
}

不過有個(gè)很明顯的問題, 當(dāng)時(shí)間戳到1003的時(shí)候,任務(wù)t1還是能夠獲取到

127.0.0.1:6379> ZRANGEBYSCORE tasks -inf 1003
1) "t1"
2) "t2"

這是因?yàn)閆RANGEBYSCORE只是查詢出來,并沒有刪除元素,刪除元素需要使用ZREM
完善一下代碼

# 偽代碼
while true {
	nowTimestamp = time.now() # 獲取當(dāng)前時(shí)間戳
	taskIds = redis.ZRANGEBYSCORE("tasks", "-inf", nowTimestamp)
	for taskId in taskIds {
	    # TODO 執(zhí)行任務(wù)處理邏輯
	    # 正常處理了調(diào)用ZREM
	    redis.ZREM("tasks", taskId)
	}
}

接下來隨著任務(wù)越來越多,上面的處理邏輯可能短時(shí)間內(nèi)也處理不完,或者單個(gè)任務(wù)處理時(shí)間較長,就會(huì)導(dǎo)致已經(jīng)到期的任務(wù)無法及時(shí)處理。
一般情況下,任務(wù)之間是沒有依賴關(guān)系,這時(shí)可以考慮橫向庫容消費(fèi)進(jìn)程,并行處理任務(wù)。

不過直接將上面的邏輯復(fù)制在多個(gè)進(jìn)程里,會(huì)有任務(wù)重復(fù)的問題。

t1t2t3t4
1000100310041004
進(jìn)程1查詢點(diǎn)
進(jìn)程2查詢點(diǎn)

就像上面一樣,可能出現(xiàn),兩個(gè)進(jìn)程同時(shí)獲取到t1任務(wù)

有兩種處理方式:

第一種 增加分布式鎖,可以基于Redis的set類型數(shù)據(jù)

代碼如下

# 偽代碼
while true {
	nowTimestamp = time.now() # 獲取當(dāng)前時(shí)間戳
	taskIds = redis.ZRANGEBYSCORE("tasks", "-inf", nowTimestamp)
	for taskId in taskIds {
		addSuccess = redis.SADD("tasks:lock", taskId)
		if addSuccess == 0 {
			# 寫入不成功 說明有其他進(jìn)程在處理該任務(wù)
			continue
		}
	    # TODO 執(zhí)行任務(wù)處理邏輯
	    
	    redis.ZREM("tasks", taskId) # 正常處理了調(diào)用ZREM 刪除任務(wù)
	    redis.SREM("tasks:lock", taskId)  # 釋放鎖, 當(dāng)然如果是任務(wù)處理失敗 也可以釋放鎖 以便可以重試任務(wù)
	}
}

如果某一段時(shí)間沒有任務(wù),會(huì)存在 ZRANGEBYSCORE 空轉(zhuǎn)的情況,增加了不必要的網(wǎng)絡(luò)調(diào)用
可以在獲取不到任務(wù)的時(shí)候,等待一個(gè)任務(wù)時(shí)間最小間隔 通常是1s

# 偽代碼
while true {
	nowTimestamp = time.now() # 獲取當(dāng)前時(shí)間戳
	taskIds = redis.ZRANGEBYSCORE("tasks", "-inf", nowTimestamp)
	if len(taskIds) == 0 {
		sleep(1)
		continue
	}
	for taskId in taskIds {
		addSuccess = redis.SADD("tasks:lock", taskId)
		if addSuccess == 0 {
			# 寫入不成功 說明有其他進(jìn)程在處理該任務(wù)
			continue
		}
	    # TODO 執(zhí)行任務(wù)處理邏輯
	    
	    redis.ZREM("tasks", taskId) # 正常處理了調(diào)用ZREM 刪除任務(wù)
	    redis.SREM("tasks:lock", taskId)  # 釋放鎖, 當(dāng)然如果是任務(wù)處理失敗 也可以釋放鎖 以便可以重試任務(wù)
	}
}

第二種 任務(wù)實(shí)際處理邏輯繼續(xù)下沉

當(dāng)前程序不進(jìn)行任務(wù)處理 只取到期的任務(wù),任務(wù)處理交給其他任務(wù)處理進(jìn)程專門處理,只向List里推送任務(wù)

# 偽代碼
# 定時(shí)獲取任務(wù)程序 保留一個(gè)
while true {
	nowTimestamp = time.now() # 獲取當(dāng)前時(shí)間戳
	taskIds = redis.ZRANGEBYSCORE("tasks", "-inf", nowTimestamp)
	
	if len(taskIds) == 0 {
		sleep(1)
		continue
	}
	for taskId in taskIds {
		redis.LPUSH("tasks:list", taskId) # 下推到隊(duì)列任務(wù)
	    redis.ZREM("tasks", taskId) # 刪除指定元素
	}
}

# 下層的任務(wù)處理程序 可以橫向擴(kuò)展運(yùn)行多個(gè)進(jìn)程
while true {
	taskId = redis.BRPOP("tasks:list", 10) # 還考慮服務(wù)器 閑置連接超時(shí) 斷開的異常
	if taskId is null {
 		continue
	}
	# TODO 執(zhí)行任務(wù)處理邏輯
	# 任務(wù)如果處理失敗需要重試 可以考慮重新ZADD到 tasks 里
}

如果生產(chǎn)消息的速度非???,也是可以考慮把 “定時(shí)獲取任務(wù)程序” 也橫向擴(kuò)展,不過需要增加分布式鎖,避免重復(fù)消費(fèi),可參考 第一種 的處理方式;也可以將任務(wù)按業(yè)務(wù)類型分類,放在不同的sorted set 中分別處理,互不影響。

到此這篇關(guān)于Redis Sorted Set類型使用及應(yīng)用場景的文章就介紹到這了,更多相關(guān)Redis Sorted Set使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis消息隊(duì)列實(shí)現(xiàn)異步秒殺功能

    Redis消息隊(duì)列實(shí)現(xiàn)異步秒殺功能

    在高并發(fā)場景下,為了提高秒殺業(yè)務(wù)的性能,可將部分工作交給 Redis 處理,并通過異步方式執(zhí)行,Redis 提供了多種數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)消息隊(duì)列,總結(jié)三種,本文詳細(xì)介紹Redis消息隊(duì)列實(shí)現(xiàn)異步秒殺功能,感興趣的朋友一起看看吧
    2025-04-04
  • 關(guān)于Redis?bigkeys命令會(huì)阻塞問題的解決

    關(guān)于Redis?bigkeys命令會(huì)阻塞問題的解決

    這篇文章主要介紹了關(guān)于Redis?bigkeys命令會(huì)阻塞問題的解決,今天分享一次Redis引發(fā)的線上事故,避免再次踩雷,實(shí)現(xiàn)快速入門,需要的朋友可以參考下
    2023-03-03
  • 通過docker和docker-compose安裝redis兩種方式詳解

    通過docker和docker-compose安裝redis兩種方式詳解

    這篇文章主要介紹了通過docker和docker-compose安裝redis的兩種方式,Docker安裝方式包括拉取鏡像、查看本地鏡像、運(yùn)行容器和測試連接,Docker Compose安裝方式包括目錄結(jié)構(gòu)、配置文件、啟動(dòng)和關(guān)閉容器、檢查啟動(dòng)情況以及查看CPU和內(nèi)存使用狀態(tài),需要的朋友可以參考下
    2024-12-12
  • 利用redis lua腳本實(shí)現(xiàn)時(shí)間窗分布式限流

    利用redis lua腳本實(shí)現(xiàn)時(shí)間窗分布式限流

    Lua是一種輕量小巧的腳本語言,Redis是高性能的key-value內(nèi)存數(shù)據(jù)庫,在部分場景下,是對(duì)關(guān)系數(shù)據(jù)庫的良好補(bǔ)充,本文給大家介紹了如何利用redis lua腳本實(shí)現(xiàn)時(shí)間窗分布式限流,需要的朋友可以參考下
    2024-03-03
  • Redis分布式鎖與Redlock算法實(shí)現(xiàn)

    Redis分布式鎖與Redlock算法實(shí)現(xiàn)

    在Redis中,可以使用多種方式實(shí)現(xiàn)分布式鎖,如使用SETNX命令或RedLock算法,本文就來介紹一下Redis分布式鎖與Redlock算法實(shí)現(xiàn),感興趣的可以了解一下
    2023-12-12
  • Redis 基礎(chǔ)教程之事務(wù)的使用方法

    Redis 基礎(chǔ)教程之事務(wù)的使用方法

    這篇文章主要介紹了Redis 基礎(chǔ)教程之事務(wù)的使用方法的相關(guān)資料,Redis 事務(wù)可以一次執(zhí)行多個(gè)命令和保證,單獨(dú)的隔離操作和原子操作需要的朋友可以參考下
    2017-08-08
  • 詳解Centos7下配置Redis并開機(jī)自啟動(dòng)

    詳解Centos7下配置Redis并開機(jī)自啟動(dòng)

    本篇文章主要介紹了Centos7下配置Redis并開機(jī)自啟動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-11-11
  • Windows安裝Redis并添加本地自啟動(dòng)服務(wù)的實(shí)例詳解

    Windows安裝Redis并添加本地自啟動(dòng)服務(wù)的實(shí)例詳解

    這篇文章主要介紹了Windows安裝Redis并添加本地自啟動(dòng)服務(wù)的實(shí)例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • redis中數(shù)據(jù)類型命令整理

    redis中數(shù)據(jù)類型命令整理

    在本篇文章里小編給大家整理的是關(guān)于redis中5種數(shù)據(jù)類型基本命令介紹,需要的朋友們可以學(xué)習(xí)下。
    2020-03-03
  • Redis中的數(shù)據(jù)過期策略詳解

    Redis中的數(shù)據(jù)過期策略詳解

    這篇文章主要介紹了Redis中的數(shù)據(jù)過期策略,文中通過示例代碼介紹的很詳細(xì),相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01

最新評(píng)論