<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>

          美團(tuán)面試官:訂單自動(dòng)關(guān)閉的功能該如何實(shí)現(xiàn)?我:有點(diǎn)懵~

          共 2938字,需瀏覽 6分鐘

           ·

          2021-02-22 12:02

          點(diǎn)擊卡片關(guān)注 ??
          來(lái)源:https://juejin.cn/post/6919095552835584008

          # 業(yè)務(wù)場(chǎng)景


          我們以訂單功能為例說(shuō)明下:生成訂單后一段時(shí)間不支付訂單會(huì)自動(dòng)關(guān)閉。最簡(jiǎn)單的想法是設(shè)置定時(shí)任務(wù)輪詢,但是每個(gè)訂單的創(chuàng)建時(shí)間不一樣,定時(shí)任務(wù)的規(guī)則無(wú)法設(shè)定,如果將定時(shí)任務(wù)執(zhí)行的間隔設(shè)置的過(guò)短,太影響效率。還有一種想法,在用戶進(jìn)入訂單界面的時(shí)候,判斷時(shí)間執(zhí)行相關(guān)操作。方式可能有很多,在這里介紹一種監(jiān)聽(tīng) Redis 鍵值對(duì)過(guò)期時(shí)間來(lái)實(shí)現(xiàn)訂單自動(dòng)關(guān)閉。


          # 實(shí)現(xiàn)思路


          在生成訂單時(shí),向 Redis 中增加一個(gè) KV 鍵值對(duì),K 為訂單號(hào),保證通過(guò) K 能定位到數(shù)據(jù)庫(kù)中的某個(gè)訂單即可,V 可為任意值。假設(shè),生成訂單時(shí)向 Redis 中存放 K 為訂單號(hào),V 也為訂單號(hào)的鍵值對(duì),并設(shè)置過(guò)期時(shí)間為 30 分鐘,如果該鍵值對(duì)在 30 分鐘過(guò)期后能夠發(fā)送給程序一個(gè)通知,或者執(zhí)行一個(gè)方法,那么即可解決訂單關(guān)閉問(wèn)題。實(shí)現(xiàn):通過(guò)監(jiān)聽(tīng) Redis 提供的過(guò)期隊(duì)列來(lái)實(shí)現(xiàn),監(jiān)聽(tīng)過(guò)期隊(duì)列后,如果 Redis 中某一個(gè) KV 鍵值對(duì)過(guò)期了,那么將向監(jiān)聽(tīng)者發(fā)送消息,監(jiān)聽(tīng)者可以獲取到該鍵值對(duì)的 K,注意,是獲取不到 V 的,因?yàn)橐呀?jīng)過(guò)期了,這就是上面所提到的,為什么要保證能通過(guò) K 來(lái)定位到訂單,而 V 為任意值即可。拿到 K 后,通過(guò) K 定位訂單,并判斷其狀態(tài),如果是未支付,更新為關(guān)閉,或者取消狀態(tài)即可。

          # 開(kāi)啟 Redis key 過(guò)期提醒


          修改 redis 相關(guān)事件配置。找到 redis 配置文件 redis.conf,查看 notify-keyspace-events 配置項(xiàng),如果沒(méi)有,添加 notify-keyspace-events Ex,如果有值,則追加 Ex,相關(guān)參數(shù)說(shuō)明如下:

          • K:keyspace 事件,事件以 keyspace@ 為前綴進(jìn)行發(fā)布

          • E:keyevent 事件,事件以 keyevent@ 為前綴進(jìn)行發(fā)布

          • g:一般性的,非特定類型的命令,比如del,expire,rename等

          • $:字符串特定命令

          • l:列表特定命令

          • s:集合特定命令

          • h:哈希特定命令

          • z:有序集合特定命令

          • x:過(guò)期事件,當(dāng)某個(gè)鍵過(guò)期并刪除時(shí)會(huì)產(chǎn)生該事件

          • e:驅(qū)逐事件,當(dāng)某個(gè)鍵因 maxmemore 策略而被刪除時(shí),產(chǎn)生該事件

          • A:g$lshzxe的別名,因此”AKE”意味著所有事件


          # 引入依賴


          在 pom.xml 中添加 org.springframework.boot:spring-boot-starter-data-redis 依賴
          <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-redisartifactId>dependency>

          # 相關(guān)配置


          定義配置 RedisListenerConfig 實(shí)現(xiàn)監(jiān)聽(tīng) Redis key 過(guò)期時(shí)間
          import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.listener.RedisMessageListenerContainer;
          @Configurationpublic class RedisListenerConfig {
          @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
          RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; }}

          定義監(jiān)聽(tīng)器 RedisKeyExpirationListener,實(shí)現(xiàn)KeyExpirationEventMessageListener?接口,查看源碼發(fā)現(xiàn),該接口監(jiān)聽(tīng)所有 db 的過(guò)期事件?keyevent@*:expired"
          import org.springframework.data.redis.connection.Message;import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;import org.springframework.data.redis.listener.RedisMessageListenerContainer;import org.springframework.stereotype.Component;
          /** * 監(jiān)聽(tīng)所有db的過(guò)期事件__keyevent@*__:expired" */@Componentpublic class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
          public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); }
          /** * 針對(duì) redis 數(shù)據(jù)失效事件,進(jìn)行數(shù)據(jù)處理 * @param message * @param pattern */ @Override public void onMessage(Message message, byte[] pattern) {
          // 獲取到失效的 key,進(jìn)行取消訂單業(yè)務(wù)處理 String expiredKey = message.toString(); System.out.println(expiredKey); }}

          推薦閱讀:

          華為正式宣布養(yǎng)豬,網(wǎng)友沸騰:支持華為自救!

          API 面試四連殺:接口如何設(shè)計(jì)?安全如何保證?簽名如何實(shí)現(xiàn)?防重如何實(shí)現(xiàn)?

          Spring Boot 中引入 MyBatisPlus 的常規(guī)流程

          垃圾代碼和優(yōu)質(zhì)代碼的區(qū)別?

          入職騰訊第九年,我辭職了

          點(diǎn)擊卡片關(guān)注,查看更多精彩


          點(diǎn)分享
          點(diǎn)點(diǎn)贊
          點(diǎn)在看
          瀏覽 72
          點(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天堂无码 | 日韩无码视频不卡 | 国产一级在线播放 |