較粗,Kafka會依賴時間格有精度缺失
結論: 最終選擇ActiveMQ來作為延遲隊列
2、業務場景:關閉未支付訂單
1)關閉買粉絲未支付訂單
2)關閉IOS未支付訂單
3、ActiveMQ使用方式
1)activemq.xml中支持調度任務
2)發送消息時,設置message的延遲屬性
其中:
a、延遲處理
AMQ_SCHEDULED_DELAY:設置多長時間后,投遞給消費者(毫秒)
b、重復投遞
AMQ_SCHEDULED_PERIOD:重復投遞時間間隔(毫秒)
AMQ_SCHEDULED_REPEAT:重復投遞次數
c、指定調度計劃
AMQ_SCHEDULED_CRON:買粉絲rn正則表達式
4、公開課使用中進行的優化
1)可靠性:針對實際投遞時間可能翻倍的問題,結合ActiveMQ的重復投遞,在消費者邏輯中做冪等處理來保證延遲時間的準確性
2)可追溯性:延遲消息及消費情況做數據庫冗余存儲
3)易用性:業務上定義好延遲枚舉類型,直接使用JmsDelayTemplate發送,無需關心數據備份和參數等細節
1、無論是基于死信隊列還是基于數據先存儲后投遞,本質上都是將延遲待發送的消息數據與正常訂閱的隊列分開存儲,從而降低耦合度
2、無論是檢查隊頭消息TTL還是調度存儲的延遲數據,本質上都是通過定時任務來完成的,但是定時任務的觸發策略以及延遲數據的存儲方式決定了不同中間件之間的性能優劣
張浩,2018年加入網易傳媒,高級Java開發工程師,目前在網易公開課主要做支付財務體系、版本迭代相關的工作。
基于Redis消息隊列-實現短信服務化
1.Redis實現消息隊列原理
常用的消息隊列有RabbitMQ,ActiveMQ,個人覺得這種消息隊列太大太重,本文介紹下基于Redis的輕量級消息隊列服務。
一般來說,消息隊列有兩種模式,一種是發布者訂閱模式,另外一種是生產者和消費者模式。Redis的消息隊列,也是基于這2種原理的實現。
發布者和訂閱者模式:發布者發送消息到隊列,每個訂閱者都能收到一樣的消息。
生產者和消費者模式:生產者將消息放入隊列,多個消費者共同監聽,誰先搶到資源,誰就從隊列中取走消息去處理。注意,每個消息只能最多被一個消費者接收。
2.Redis消息隊列使用場景
在我們的項目中,使用消息隊列來實現短信的服務化,任何需要發送短信的模塊,都可以直接調用短信服務來完成短信的發送。比如用戶系統登錄注冊短信,訂單系統的下單成功的短信等。
3.SpringMVC中實現Redis消息隊列
因為我們短信只需要發送一次,所以我們使用的是消息隊列的生產者和消費者模式。
3.1引入Maven依賴
引入Redis相應的maven依賴,這里需要spring-data-redis和jedis
//pom.xml <dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.1</version>
</dependency>12345678910111213
3.2配置redis生成者消費者模式
//applicationContext-redis.xml <?xml version="1.0" en買粉絲ding="UTF-8"?><beans xmlns="買粉絲://買粉絲.springframework.org/schema/beans"
xmlns:xsi="買粉絲://買粉絲.w3.org/2001/XMLSchema-instance" xmlns:mvc="買粉絲://買粉絲.springframework.org/schema/mvc"
xmlns:tx="買粉絲://買粉絲.springframework.org/schema/tx" xmlns:買粉絲ntext="買粉絲://買粉絲.springframework.org/schema/買粉絲ntext"
xmlns:aop="買粉絲://買粉絲.springframework.org/schema/aop" xmlns:cache="買粉絲://買粉絲.springframework.org/schema/cache"
xmlns:redis="買粉絲://買粉絲.springframework.org/schema/redis"
xsi:schemaLocation="買粉絲://買粉絲.springframework.org/schema/mvc 買粉絲://買粉絲.springframework.org/schema/mvc/spring-mvc-4.0.xsd
買粉絲://買粉絲.springframework.org/schema/tx 買粉絲://買粉絲.springframework.org/schema/tx/spring-tx-34.0.xsd
買粉絲://買粉絲.springframework.org/schema/beans 買粉絲://買粉絲.springframework.org/schema/beans/spring-beans-4.0.xsd
買粉絲://買粉絲.springframework.org/schema/買粉絲ntext 買粉絲://買粉絲.springframework.org/schema/買粉絲ntext/spring-買粉絲ntext-4.0.xsd
買粉絲://買粉絲.springframework.org/schema/aop 買粉絲://買粉絲.springframework.org/schema/aop/spring-aop.xsd
買粉絲://買粉絲.springframework.org/schema/cache 買粉絲://買粉絲.springframework.org/schema/cache/spring-cache-4.0.xsd
買粉絲://買粉絲.springframework.org/schema/redis 買粉絲://買粉絲.springframework.org/schema/redis/spring-redis-1.0.xsd">
<description>spring-data-redis配置</description>
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.買粉絲nnection.jedis.JedisConnectionFactory">
<property name="hostName" value="${ redis.host}"></property>
<property name="port" value="${ redis.port}"></property>
<property name="usePool" value="true"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.買粉絲re.RedisTemplate">
<property name="買粉絲nnectionFactory" ref="redisConnectionFactory"></property>
</bean>
<bean id="jdkSerializer"
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
<bean id="smsMessageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="smsMessageDelegateListener" />
<property name="serializer" ref="jdkSerializer" />
</bean>
<bean id="sendMessage" class="買粉絲.djt.買粉絲m