<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          領(lǐng)導(dǎo):誰再用Redis過期監(jiān)聽實(shí)現(xiàn)關(guān)閉訂單,立馬滾蛋!

          共 2126字,需瀏覽 5分鐘

           ·

          2022-06-27 23:58

          來源:www.cnblogs.com/Finley/p/16395466.html

          前言

          在電商、支付等領(lǐng)域,往往會(huì)有這樣的場景,用戶下單后放棄支付了,那這筆訂單會(huì)在指定的時(shí)間段后進(jìn)行關(guān)閉操作,細(xì)心的你一定發(fā)現(xiàn)了像某寶、某東都有這樣的邏輯,而且時(shí)間很準(zhǔn)確,誤差在1s內(nèi);那他們是怎么實(shí)現(xiàn)的呢?

          一般實(shí)現(xiàn)的方法有幾種:

          1. 使用 rocketmq、rabbitmq、pulsar 等消息隊(duì)列的延時(shí)投遞功能
          2. 使用 redisson 提供的 DelayedQueue

          有一些方案雖然廣為流傳但存在著致命缺陷,不要用來實(shí)現(xiàn)延時(shí)任務(wù)

          1. 使用 redis 的過期監(jiān)聽
          2. 使用 rabbitmq 的死信隊(duì)列
          3. 使用非持久化的時(shí)間輪

          redis 過期監(jiān)聽

          在 Redis 官方手冊的keyspace-notifications: timing-of-expired-events中明確指出:

          Basically expired events are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero

          redis 自動(dòng)過期的實(shí)現(xiàn)方式是:定時(shí)任務(wù)離線掃描并刪除部分過期鍵;在訪問鍵時(shí)惰性檢查是否過期并刪除過期鍵。redis 從未保證會(huì)在設(shè)定的過期時(shí)間立即刪除并發(fā)送過期通知。實(shí)際上,過期通知晚于設(shè)定的過期時(shí)間數(shù)分鐘的情況也比較常見。

          此外鍵空間通知采用的是發(fā)送即忘(fire and forget)策略,并不像消息隊(duì)列一樣保證送達(dá)。當(dāng)訂閱事件的客戶端會(huì)丟失所有在斷線期間所有分發(fā)給它的事件。

          這是一種比定時(shí)掃描數(shù)據(jù)庫更 “LOW” 的解決方案,請不要使用。

          rabbitmq 死信

          死信(Dead Letter) 是 rabbitmq 提供的一種機(jī)制。當(dāng)一條消息滿足下列條件之一那么它會(huì)成為死信:

          • 消息被否定確認(rèn)(如channel.basicNack) 并且此時(shí)requeue 屬性被設(shè)置為false。
          • 消息在隊(duì)列的存活時(shí)間超過設(shè)置的TTL時(shí)間
          • 消息隊(duì)列的消息數(shù)量已經(jīng)超過最大隊(duì)列長度

          若配置了死信隊(duì)列,死信會(huì)被 rabbitmq 投到死信隊(duì)列中。

          在 rabbitmq 中創(chuàng)建死信隊(duì)列的操作流程大概是:

          • 創(chuàng)建一個(gè)交換機(jī)作為死信交換機(jī)
          • 在業(yè)務(wù)隊(duì)列中配置 x-dead-letter-exchange 和 x-dead-letter-routing-key,將第一步的交換機(jī)設(shè)為業(yè)務(wù)隊(duì)列的死信交換機(jī)
          • 在死信交換機(jī)上創(chuàng)建隊(duì)列,并監(jiān)聽此隊(duì)列

          死信隊(duì)列的設(shè)計(jì)目的是為了存儲(chǔ)沒有被正常消費(fèi)的消息,便于排查和重新投遞。死信隊(duì)列同樣也沒有對(duì)投遞時(shí)間做出保證,在第一條消息成為死信之前,后面的消息即使過期也不會(huì)投遞為死信。

          為了解決這個(gè)問題,rabbit 官方推出了延遲投遞插件 rabbitmq-delayed-message-exchange ,推薦使用官方插件來做延時(shí)消息。

          這里說點(diǎn)題外話,使用 redis 過期監(jiān)聽或者 rabbitmq 死信隊(duì)列做延時(shí)任務(wù)都是以設(shè)計(jì)者預(yù)想之外的方式使用中間件,這種出其不意必自斃的行為通常會(huì)存在某些隱患,比如缺乏一致性和可靠性保證,吞吐量較低、資源泄漏等。比較出名的一個(gè)事例是很多人使用 redis 的 list 作為消息隊(duì)列,以致于最后作者看不下去寫了 disque 并最后演變?yōu)?redis stream。工作中還是盡量不要濫用中間件,用專業(yè)的組件做專業(yè)的事

          時(shí)間輪

          時(shí)間輪是一種很優(yōu)秀的定時(shí)任務(wù)的數(shù)據(jù)結(jié)構(gòu),然而絕大多數(shù)時(shí)間輪實(shí)現(xiàn)是純內(nèi)存沒有持久化的。運(yùn)行時(shí)間輪的進(jìn)程崩潰之后其中所有的任務(wù)都會(huì)灰飛煙滅,所以奉勸各位勇士謹(jǐn)慎使用。

          redisson delayqueue

          redisson delayqueue 是一種基于 redis zset 結(jié)構(gòu)的延時(shí)隊(duì)列實(shí)現(xiàn)。delayqueue 中有一個(gè)名為 timeoutSetName 的有序集合,其中元素的 score 為投遞時(shí)間戳。delayqueue 會(huì)定時(shí)使用 zrangebyscore 掃描已到投遞時(shí)間的消息,然后把它們移動(dòng)到就緒消息列表中。

          delayqueue 保證 redis 不崩潰的情況下不會(huì)丟失消息,在沒有更好的解決方案時(shí)不妨一試。

          在數(shù)據(jù)庫索引設(shè)計(jì)良好的情況下,定時(shí)掃描數(shù)據(jù)庫中未完成的訂單產(chǎn)生的開銷并沒有想象中那么大。在使用 redisson delayqueue 等定時(shí)任務(wù)中間件時(shí)可以同時(shí)使用掃描數(shù)據(jù)庫的方法作為補(bǔ)償機(jī)制,避免中間件故障造成任務(wù)丟失。

          結(jié)論

          1. 首先推薦使用 rocketmq、pulsar 等擁有定時(shí)投遞功能的消息隊(duì)列。
          2. 在不方便獲得專業(yè)消息隊(duì)列時(shí)可以考慮使用 redisson delayqueue 等基于 redis 的延時(shí)隊(duì)列方案,但要為 redis 崩潰等情況設(shè)計(jì)補(bǔ)償保護(hù)機(jī)制。
          3. 在無法使用 redisson delayqueue 等方案時(shí)可以考慮使用時(shí)間輪。由于時(shí)間輪重啟遠(yuǎn)比 redis 重啟要頻繁,定時(shí)掃庫等保護(hù)機(jī)制更為重要。
          4. 永遠(yuǎn)不要使用 redis 過期監(jiān)聽實(shí)現(xiàn)定時(shí)任務(wù)。
          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情视频激情五月天 | 日韩中文字幕在线视频 | 色多多在线网址 | 亚洲最大的黄色网址 | 综合电影Av |