Redis 有序集合(zset)取交集(zinterstore)操作耗时测试
? ? ? ? ?取交集的場景很多,比如公眾號文章顯示有多少個好友已讀,又或者群聊成員列表顯示有多少個好友已經(jīng)入群。最近遇到一個類似場景,一開始的覺得線上數(shù)據(jù)量較大,redis 取交集操作時間復(fù)雜度在O(N),實時計算會不會不合適?是否離線計算更好?請教了組內(nèi)資深大佬,大佬說數(shù)據(jù)量不大的情況下redis計算挺快的。聽了之后感覺需要實際測試一下,不然貿(mào)然上線心里沒底。下面是測試流程,有需要的同學(xué)可以參考下。
? ? ? ? 假定測試目標是統(tǒng)計在線用戶中付費用戶數(shù)量,測試結(jié)果如下圖,先說結(jié)論:耗時和數(shù)據(jù)集大小以及數(shù)據(jù)集重合度有關(guān)(廢話,耗時肯定和數(shù)據(jù)集大小有關(guān)^_^)。測試結(jié)果也和zinterstore 的時間復(fù)雜度是一致的。下圖右側(cè)是提高重合度的結(jié)果,耗時明顯有增加。
ZINTERSTORE 時間復(fù)雜度: O(N*K)+O(M*log(M)) 這里N表示有序集合中成員數(shù)最少的數(shù)字,K表示有序集合數(shù)量。M表示結(jié)果集中重合的數(shù)量。測試設(shè)備:
????????騰訊云服務(wù)器 16核 32G內(nèi)存
數(shù)據(jù)集通過redis lua腳本跑出
create_data.lua 腳本:
-- 1000 用戶量 redis.call("del","online_user_1000", "rich_user_1000","online_user_5000","rich_user_5000","online_user_10000","rich_user_10000","online_user_50000","rich_user_50000","online_user_100000","rich_user_100000") for i = 1, 1000, 1 do redis.call("zadd", "online_user_1000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_1000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 5000 用戶量 for i = 1, 5000, 1 do redis.call("zadd", "online_user_5000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_5000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 10000 用戶量 for i = 1, 10000, 1 do redis.call("zadd", "online_user_10000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_10000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 50000 用戶量 for i = 1, 50000, 1 do redis.call("zadd", "online_user_50000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_50000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 100000 用戶量 for i = 1, 100000, 1 do redis.call("zadd", "online_user_100000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_100000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 500000 用戶量 for i = 1, 500000, 1 do redis.call("zadd", "online_user_500000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_500000", math.random(1000000)*math.random(100000), math.random(10000000)) end-- 1000000 用戶量 for i = 1, 1000000, 1 do redis.call("zadd", "online_user_1000000", math.random(1000000)*math.random(100000), math.random(10000000)) redis.call("zadd", "rich_user_1000000", math.random(1000000)*math.random(100000), math.random(10000000)) endreturn "OK"?測試工具:redis-benchmark
測試命令如下,-n表示執(zhí)行次數(shù)
redis-benchmark -n 10000 zinterstore inter_user_1000 2 online_user_1000 rich_user_1000 redis-benchmark -n 10000 zinterstore inter_user_5000 2 online_user_5000 rich_user_5000 redis-benchmark -n 10000 zinterstore inter_user_10000 2 online_user_10000 rich_user_10000 redis-benchmark -n 10000 zinterstore inter_user_50000 2 online_user_50000 rich_user_50000 redis-benchmark -n 10000 zinterstore inter_user_100000 2 online_user_100000 rich_user_100000 redis-benchmark -n 10000 zinterstore inter_user_500000 2 online_user_500000 rich_user_500000 redis-benchmark -n 10000 zinterstore inter_user_1000000 2 online_user_1000000 rich_user_1000000測試截圖:
? ? ? ? ?在我的業(yè)務(wù)場景里,數(shù)據(jù)集一般在1萬以下,上限不會超過100萬,結(jié)合本次實測結(jié)果,實時計算應(yīng)該沒啥問題。測試過程中也發(fā)現(xiàn),雖然單個請求耗時不大,但是如果存在大量請求,并且這些請求對應(yīng)數(shù)據(jù)規(guī)模很大,則勢必占用redis server大量處理時間,帶來普通請求的延遲或者超時,這一點也需要在業(yè)務(wù)中考慮。
總結(jié)
以上是生活随笔為你收集整理的Redis 有序集合(zset)取交集(zinterstore)操作耗时测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux JQ 命令学习笔记
- 下一篇: java重写paint方法时怎么样不覆盖