在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    Redis 定長隊列的探索和實踐

    Redis 定長隊列的探索和實踐

    vivo 互聯(lián)網(wǎng)服務器團隊 – Wang Zhi

    一、業(yè)務背景

    從技術的角度來說,技術方案的選型都是受限于實際的業(yè)務場景,都以解決實際業(yè)務場景為目標。

    在我們的實際業(yè)務場景中,需要以游戲維度收集和上報行為數(shù)據(jù),考慮數(shù)據(jù)的量級,執(zhí)行盡最大努力交付且允許數(shù)據(jù)的部分丟棄。

    數(shù)據(jù)上報支持游戲的維度的批量上報,支持同一款游戲128個行為進行批量上報。

    數(shù)據(jù)上報需要時效控制,上報的數(shù)據(jù)必須是上報時刻的前3分鐘的數(shù)據(jù)。

    整體數(shù)據(jù)的業(yè)務形態(tài)如下圖所示:

    二、技術選型

    從業(yè)務的角度來說包含數(shù)據(jù)的收集和數(shù)據(jù)的上報,我們把數(shù)據(jù)的收集比作生產(chǎn)者,數(shù)據(jù)的上報比作消費者,是一個典型的生產(chǎn)消費模型。

    生產(chǎn)消費模型在JVM進程內(nèi)部通過隊列+鎖或者無鎖的Disruptor來實現(xiàn),在跨進程場景下通過MQ(RocketMQ/kafka)進行處理解耦。

    但是細化到具體業(yè)務場景來看,消息的消費有諸多限制,包括: 游戲維度的批量行為上報,行為上報的時效限制,細化到各個技術方案選型進行對比。

    方案一

    使用RocketMQ 或者Kafaka等消息隊列來存儲上報的消息,但是消費側需要考慮在業(yè)務進程中按照游戲維度進行聚合,其中技術細節(jié)涉及按照游戲維度進行拆分,在滿足消息時效性和批量性的前提下觸發(fā)上報。在這種方案下消息中間件扮演的角色本質(zhì)上消息的中轉(zhuǎn)站, 沒有解決任何業(yè)務場景中提及的游戲維度拆分、批量性和時效性。

    方案二

    在方案一的基礎上,尋求一種技術方案來解決游戲維度的 消息分組、批量消費 、時效性 。通過Redis的list結構來實現(xiàn)隊列(進一步要求實現(xiàn)定長隊列)來解決游戲維度的消息分組;通過Redis的list支持的Lrange來實現(xiàn)批量消費;通過業(yè)務側的多線程來解決時效問題,針對高頻的游戲使用單獨的線程池進行處理,上述兩個手段能夠保證消費速度大于生產(chǎn)速度。

    方案對比

    對比兩種方案后決定使用Redis的實現(xiàn)了一個偽消息中間件:

  • 通過List對象實現(xiàn)定長隊列來保存游戲維度的行為消息(以游戲作為key的List對象來保存用戶行為);
  • 通過List來保存所有的存在行為數(shù)據(jù)的游戲列表;
  • 通過Set來進行去重判斷來保證2中的List對象的唯一性。
  • 整體的技術方案如下圖所示:

    生產(chǎn)過程

    步驟一:游戲維度的某行為數(shù)據(jù)PUSH到游戲維度的隊列當中。

    步驟二:判斷游戲是否在游戲的集合Set中,如果在就直接返回,如果不在進行步驟三。

    步驟三:往游戲列表中PUSH游戲。

    消費過程

    步驟一:從游戲?qū)ο蟮牧斜碇醒h(huán)取出一款游戲。

    步驟二:通過步驟一獲取的游戲?qū)ο笕ピ撚螒驅(qū)ο蟮男袨閿?shù)據(jù)隊列中批量獲取數(shù)據(jù)處理。

    三、技術原理

    在Redis的支持命令中,在List和Set的基礎命令,結合Lua腳本來實現(xiàn)整個技術方案。

    消息數(shù)據(jù)層面,通過單獨的List循環(huán)維護待消費的游戲維度的數(shù)據(jù),每個游戲維度使用定長的List來保存消息。

    消息生產(chǎn)過程中,通過結合List的llen+lpop+rpush來實現(xiàn)游戲維度的定長隊列,保證隊列的長度可控。

    消息消費過程中,通過結合List的lrange+ltrim來實現(xiàn)游戲維度的消息的批量消費。

    在整個執(zhí)行的復雜度層面,需要保證時間復雜度在0(N)常量維度,保證時間可控。

    3.1 Lua 腳本

    EVAL script numkeys key [key …] arg [arg …] 時間復雜度:取決于腳本本身的執(zhí)行的時間復雜度。 > eval “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 2 key1 key2 first second1) “key1″2) “key2″3) “first”4) “second” Redis uses the same Lua interpreter to run all the commands.Also Redis guarantees that a script is executed in an atomic way:no other script or Redis command will be executed while a script is being executed.This semantic is similar to the one of MULTI / EXEC.From the point of view of all the other clients the effects of a script are either still not visible or already completed.

    Redis采用相同的Lua解釋器去運行所有命令,我們可以保證,腳本的執(zhí)行是原子性的。作用就類似于加了MULTI/EXEC。

    • Lua 腳本內(nèi)多個命令以原子性的方式執(zhí)行,保證了命令執(zhí)行的線程安全。
    • Lua 腳本結合List命令實現(xiàn)定長隊列,實現(xiàn)批量消費。
    • Lua 腳本僅支持單個key的操作,不支持多key的操作。

    3.2 List 對象

    LLEN key 計算List的長度 時間復雜度:O(1)。 LPOP key [count] 從List的左側移除元素 時間復雜度:O(N),N為移除元素的個數(shù)。 RPUSH key element [element …] 從List的右側保存元素 時間復雜度:O(N),N為保存元素的個數(shù)。

    • List的基礎命令包括計算List的長度,移除數(shù)據(jù),添加數(shù)據(jù),整體命令的復雜度都在O(N)的常量時間。
    • 整合上述三個命令,我們能保證實現(xiàn)固定長度的隊列,通過判斷隊列長度是否達到定長結合新增隊列元素和移除隊列元素來完成。

    LRANGE key start end 時間復雜度:O(S+N), S為偏移量start, N為指定區(qū)間內(nèi)元素的數(shù)量。 下標(index)參數(shù) start 和 stop 都以 0 為底,也就是說,以 0 表示列表的第一個元素,以 1 表示列表的第二個元素,以此類推。 你也可以使用負數(shù)下標,以 -1 表示列表的最后一個元素, -2 表示列表的倒數(shù)第二個元素,以此類推。 LTRIM key start stop 時間復雜度:O(N) where N is the number of elements to be removed by the operation. 修剪(trim)一個已存在的 list,這樣 list 就會只包含指定范圍的指定元素。

    • List的基礎命令包括批量返回數(shù)據(jù)和裁剪數(shù)據(jù),整體命令的復雜度都在O(N)的常量時間。
    • 整合上述兩個命令,我們能夠批量消費數(shù)據(jù)并移除隊列數(shù)據(jù),通過LRANGE批量返回數(shù)據(jù)并通過LTRIM保留剩余數(shù)據(jù)。

    3.3 Set 對象

    SADD key member [member …] 往Set集合添加數(shù)據(jù)。 時間復雜度:O(1)。 SISMEMBER key member 判斷Set集合是否存在元素。 時間復雜度:O(1)。

    • 通過Set集合來保證數(shù)據(jù)的唯一性,且時間復雜度可控。

    四、技術應用

    4.1 生產(chǎn)消息

    定義LUA腳本 CACHE_NPPA_EVENT_LUA = “local retVal = 0 ” + “local key = KEYS[1] ” + “local num = tonumber(ARGV[1]) ” + “local val = ARGV[2] ” + “local expire = tonumber(ARGV[3]) ” + “if (redis.call(‘llen’, key) < num) then redis.call('rpush', key, val) " + "else redis.call('lpop', key) redis.call('rpush', key, val) retVal = 1 end " + "redis.call('expire', key, expire) return retVal"; 執(zhí)行LUA腳本 String data = JSON.toJSONString(nppaBehavior); Long retVal = (Long)jedisClusterTemplate.eval(CACHE_NPPA_EVENT_LUA, 1, NPPA_PREFIX + nppaBehavior.getGamePackage(), String.valueOf(MAX_GAME_EVENT_PER_GAME), data, String.valueOf(NPPA_TTL_MINUTE * 60)); 執(zhí)行效果 實現(xiàn)固長隊列的數(shù)據(jù)存儲并設置過期時間

    • 通過整合llen+rpush+lpop三個命令實現(xiàn)定長隊列。
    • 通過lua腳本保證上述命令的原子性執(zhí)行。
    • 整體的執(zhí)行流程如上圖所示,核心理念通過lua腳本的原子性保證了隊列長度計算(llen)、隊列數(shù)據(jù)移除(lpop)、隊列數(shù)據(jù)保存(rpush)的原子性執(zhí)行。

    4.2 消費消息

    定義LUA腳本 QUERY_NPPA_EVENT_LUA = “local data = {} ” + “local key = KEYS[1] ” + “local num = tonumber(ARGV[1]) ” + “data = redis.call(‘lrange’, key, 0, num) redis.call(‘ltrim’, key, num+1, -1) return data”; 執(zhí)行LUA腳本 Integer batchSize = NppaConfigUtils.getInteger(“nppa.report.batch.size”, 1); Object result = jedisClusterTemplate.eval(QUERY_NPPA_EVENT_LUA, 1,NPPA_PREFIX + gamePackage, String.valueOf(batchSize)); 執(zhí)行效果 取固定數(shù)量的對象,然后保留隊列的剩余的消息對象。

    • 通過整合lrange+ltrim兩個命令實現(xiàn)消息的批量消費。
    • 通過lua腳本保證上述命令的原子性執(zhí)行。
    • 整體的執(zhí)行流程如上圖所示,核心理念通過lua腳本的原子性保證了數(shù)據(jù)獲?。↙range)和數(shù)據(jù)裁剪(Ltrim)的原子性執(zhí)行。
    • 整體的消費流程選擇pull模式,通過多線程循環(huán)輪詢可消費的隊列進行消費。與借助于redis的pub/sub的通知機制實現(xiàn)消費流程的push模式相比,pull模式成本更低效果更佳。

    4.3 注意事項

    • Redis集群模式下,執(zhí)行Lua腳本建議傳單key,多key會報重定向錯誤。
    • 在不同的Redis版本下,Lua腳本針對null的返回值處理不同,參考官方文檔。
    • 消費者的消費過程中通過循環(huán)遍歷游戲列表,然后根據(jù)游戲去獲取對應的消息對象,但是不同的游戲?qū)臒岫炔煌?,所以在消費端我們通過配置的方式為熱門游戲單獨開啟消費線程進行消費,相當于針對不同游戲配置不同優(yōu)先級的消費者。

    五、線上效果

    • 生產(chǎn)和消費的QPS約為1w qps左右,整體上報QPS通過批量上報后會遠低于生產(chǎn)的消息生產(chǎn)和消費的QPS。
    • 整體數(shù)據(jù)的使用游戲包名作為key進行存儲,性能上不存在熱點的問題。

    六、適用場景

    在描述完方案的原理和實現(xiàn)細節(jié)之后,進一步對適用的業(yè)務場景進行下總結。整體方案是基于redis的基本數(shù)據(jù)結構構建一個偽消息隊列,用以解決 消息的單個生產(chǎn)批量消費 的場景,通過多key形式實現(xiàn)消息隊列的多Topic模式,重要的是能夠借助于redis的原生能力在O(N)的時間復雜度完成批量消費。另外該方案也可以降級作為實現(xiàn)先進先出定長的日志隊列。

    七、總結

    本文主要探索在特定業(yè)務場景下通過Redis的原生命令實現(xiàn)類MQ的功能,創(chuàng)新式的通過Lua腳本組合Redis的List的基礎命令,實現(xiàn)了消息的分組,消息的定長隊列,消息的批量消費功能;整體解決方案在線上環(huán)境落地并平穩(wěn)運行,為特定場景提供了一種通用的解決方案。

    作者:Wang Zhi

    來源:微信公眾號:vivo互聯(lián)網(wǎng)技術

    出處:https://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&mid=2247494331&idx=1&sn=273c10d8c46068db850f1961be2f436b

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年8月8日 12:20
    下一篇 2022年8月8日 12:20

    相關推薦

    • 請問秀兒是你嗎什么梗

      簡要回答 秀兒是你嗎這句話其實沒有貶義的含義,這句話的意思是形容內(nèi)容有趣,優(yōu)秀的意思。 現(xiàn)在很多人喜歡刷視頻,所以很多人會拍一些視頻供大家觀看,有些觀看者會在下面評論,有些人會評論…

      2022年11月27日
    • dnf一鍵拾取(dnf一鍵拾取是全圖的嗎)

      今天小編給各位分享dnf一鍵拾取的知識,其中也會對dnf一鍵拾取是全圖的嗎進行解釋,如果能碰巧解決你現(xiàn)在面臨的問題,別忘了關注本站,現(xiàn)在開始吧! dnf如何一鍵拾取物品 dnf一鍵…

      2022年11月27日
    • 《寶可夢朱紫》3天銷量破千萬(寶可夢朱紫3天銷量破千萬了)

      開局只能選一種御三家,不能同時擁有全部這是游戲設計的劇情不能更改的。 已經(jīng)偷跑了寶可夢朱紫將于11月18日正式發(fā)售,而目前已有實體卡帶偷跑御三家進化型終于在泄露了,新葉喵站了起來,…

      2022年11月27日
    • 【周末玩什么】3天銷量破千萬的《寶可夢 朱/紫》,為何被評價為“又爛又好”

      本周推薦《寶可夢 朱/紫》和《第七境》。 本月18號《寶可夢 朱/紫》全球發(fā)售。截至發(fā)稿日,本作的MC媒體均分從79分跌至75分,玩家評分更是只有可憐的2.9分。發(fā)售之初,國內(nèi)關于…

      2022年11月27日
    • cad連續(xù)標注快捷鍵(cad連續(xù)標注快捷鍵)

      本文主要講的是cad連續(xù)標注快捷鍵,以及和cad連續(xù)標注快捷鍵相關的知識,如果覺得本文對您有所幫助,不要忘了將本文分享給朋友。 cad中連續(xù)標注快捷鍵 CAD尺寸標準快捷命令:DL…

      2022年11月27日
    • 微軟表示:《GTA6》預計將于2024年發(fā)售

      微軟表示:《GTA6》預計將于2024年發(fā)售 近日,微軟在回應英國競爭與市場管理局(CMA)調(diào)查其收購動視暴雪時提到,《GTA6》預計將在2024年發(fā)售。 “備受期待的《GTA6》…

      2022年11月26日
    • 劉畊宏回應梅西輸球后哭了:跳操流汗到眼睛 剛好有點流鼻水

      11月23日,劉畊宏發(fā)言回應自己再梅西輸球后流淚的消息,他寫道:“我是有些難過… 然后…跳操流汗到眼睛,剛好有點流鼻水,阿根廷之后的比賽會贏的!”據(jù)悉,11月22日的世界杯比賽中,…

      2022年11月26日
    • 英雄聯(lián)盟手游好玩嗎(英雄聯(lián)盟手游好玩還是端游好玩)

      簡要回答 非常好玩,英雄聯(lián)盟手游這款游戲已經(jīng)正式的進行公測,這款游戲是以5v5為模式進行對戰(zhàn)的,它是以英雄聯(lián)盟端游為原型進行開發(fā),里面的每一種玩法基本都沿襲了端游的特點。 01 這…

      2022年11月25日
    • 游戲平臺有哪些(游戲平臺有哪些)

      簡要回答 游戲平臺指的是多人通過互聯(lián)網(wǎng)在線游戲的平臺,例如qq游戲,聯(lián)眾世界,浩方電競平臺,VS競技游戲平臺等,只要你下載平臺,下載相關游戲,就能實現(xiàn)對戰(zhàn),擺脫了局域網(wǎng)的限制。 詳…

      2022年11月25日
    • 好玩的塔防游戲(好玩的單機塔防手機游戲)

      簡要回答 對于游戲愛好者來說塔防游戲并不陌生,畢竟很多人一開始玩的就是塔防游戲,比如大家都知道的植物大戰(zhàn)僵尸,而且如今植物大戰(zhàn)僵尸還在大家的視野里面,很多博主也會用植物大戰(zhàn)僵尸玩很…

      2022年11月25日

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息