springboot+redis做過期事件通知業務

實習小生發表於2020-07-23

springboot+redis做過期事件通知

博主也是初次體驗,不足之處多多指教

我的業務場景

系統管理員要給維護員分配巡查路口設施的工作,由於路口比較多,管理員不知道哪些路口已經被分配了,況且過了一個時間週期後,所有的路口要再次被巡查。

思路

我建立了一個表,裡面是所有路口和是否已經分配的狀態

利用redis的鍵過期事件來做這個業務。

  1. 管理員給維護員分配了路口的時候把那些路口狀態修改為不可分配,然後把路口新增到redis,以intersection:開頭+id作為key,value為"",設定上過期時間(這個過期時間就是那個時間週期)。
  2. 管理員查詢路口時預設只檢視可分配狀態的路口。
  3. 利用redis的鍵過期事件通知得到key,再把路口id解析出來,然後修改該路口狀態為可分配。

修改redis配置檔案,以windows版本為例

notify-keyspace-events的值修改未 Ex,預設的可能是**notify-keyspace-events "" **,然後重啟redis

測試

開一個redis客戶端1
#redis目錄下 注意__是由兩個下劃線組成的 

127.0.0.1:6379> psubscribe __keyevent@0__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@0__:expired"
3) (integer) 1
再開一個redis客戶端2
127.0.0.1:6379> set a 111 ex 5
客戶端1的結果
1) "pmessage"
2) "__keyevent@0__:expired"
3) "__keyevent@0__:expired"
4) "a"

keyevent@0:expired解析
key 鍵
event 事件
@0 第0個資料庫
expired 過期
不懂的可以多搜搜相關資料,我也是第一次弄!座標

上程式碼

新增依賴 不貼版本了

<!-- apache-commons -->
      <dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
      </dependency>
<!-- redis -->
      <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>

redis配置 redis的database要和下面的Java程式碼裡寫的一樣!!!!!!

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: 123456
    url: jdbc:mysql://localhost:3306/zhjtyw-dev?characterEncoding=UTF8&useSSL=false&serverTimezone=GMT%2B8
    username: root
  redis:
    database: 0
    host: 127.0.0.1
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        max-wait: -1
        min-idle: 0
    port: 6379
    password: 123456
  cache:
    type: redis

配置redis監聽器

/**
 * @author: taoym
 * @date: 2020/7/23 9:34
 * @desc: redis監聽器
 */
@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

配置

/**
 * @author: taoym
 * @date: 2020/7/23 9:38
 * @desc: 監聽器
 */
@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    @Autowired
    private IntersectionPatrolStatusService intersectionPatrolStatusService;
    // 配置監聽哪個頻道
    private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@0__:expired");

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    protected void doRegister(RedisMessageListenerContainer listenerContainer) {
        // 頻道可以是多,多個傳list
        listenerContainer.addMessageListener(this,KEYEVENT_EXPIRED_TOPIC);
    }

    /**
     * @author: taoym
     * @date: 2020/7/17 16:12
     * @desc: redis失效事件
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 使用者做自己的業務處理即可,注意message.toString()可以獲取失效的key
        String expiredKey = message.toString();
        expiredKey = expiredKey.substring(1,expiredKey.length()-1);
        if(expiredKey.startsWith("intersection"+ RegexConstant.COLON)){
            String[] split = expiredKey.split(RegexConstant.COLON);
            Integer id = Integer.valueOf(split[1]);
            ReqUpdateIntersectionPatrolStatusDTO data = new ReqUpdateIntersectionPatrolStatusDTO();
            data.setId(id);
            data.setStatus(IntersectionPatrolStatusEnum.CAN_DISTRIBUTION.getCode());
            int i = intersectionPatrolStatusService.updateIntersectionPatrolStatus(data);
            log.info("巡查路口的週期已經過,可以開始下次巡查");
        }
    }
}

結束語

利用redis的鍵過期事件能做很多事,多多探索,多從網上查查資料!
最後----【多讀書、多看報、少吃零食、多睡覺0.0】

相關文章