1. 程式人生 > 其它 >通過redis鍵空間通知實現日程的提醒通知

通過redis鍵空間通知實現日程的提醒通知

什麼是延遲任務?

顧明思議,我們把需要延遲執行的任務叫做延遲任務

延遲任務的使用場景有以下這些:

  1. 紅包 24 小時未被查收,需要延遲執退還業務;
  2. 每個月賬單日,需要給使用者傳送當月的對賬單;
  3. 訂單下單之後 30 分鐘後,使用者如果沒有付錢,系統需要自動取消訂單。
  4. 新增日程事項選擇某個時間後,需要到點或提前多久,或每天,或每週等,傳送當前日程通知。

等事件都需要使用延遲任務。

使用 Redis 實現延遲任務的方法大體可分為兩類:

  1. 和通過鍵空間通知的方式
  2. 通過 zset 資料判斷的方式。

 1.通過鍵空間通知

預設情況下 Redis 伺服器端是不開啟鍵空間通知的,需要我們通過 config set notify-keyspace-events Ex

 的命令手動開啟,

開啟鍵空間通知後,我們就可以拿到每個鍵值過期的事件,我們利用這個機制實現了給每個人開啟一個定時任務的功能,實現程式碼如下:

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/*
* redis資料連線池的工具類
* 這個有點老 * @author lcl
*/ @Component public
class JedisUtils { private static JedisPool pool; static { //讀取配置檔案 String host = "localhost"; //獲取埠號 int port = Integer.parseInt("6379"); //獲取最大連線數 int maxTotal = Integer.parseInt("50"); //獲取閒時連線數 int maxIdle = Integer.parseInt("20");
//建立連線池配置物件 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMaxTotal(maxTotal); //建立連線池物件 pool = new JedisPool(jedisPoolConfig, host, port); } //建立方法 連線池物件 public static Jedis getJedis(){ return pool.getResource(); } //釋放資源 public static void close(Jedis jedis){ if(jedis!=null){ jedis.close(); } } private static void close(JedisPool pool){ if (pool!=null){ pool.close(); } } }

 Service

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

/**
 * 通過redis實現 定時任務傳送通知
 * @author lcl
 */
@Component
public class RedisTaskServiceImpl implements ApplicationRunner
{

    private static final Logger log = LoggerFactory.getLogger(RedisTaskServiceImpl.class);

    /**
     * 鍵空間通知
     */
    public void doTask()
    {
        //連線redis的工具類,你得自己設定一下
        Jedis jedis = JedisUtils.getJedis();
        // 訂閱過期訊息
        jedis.psubscribe(new JedisPubSub()
        {
            @Override
            public void onPMessage(String pattern, String channel, String message)
            {
                /**
                 *    我存了兩個key
                 *    一個是過期時間的,一個是不過期的
                 *    如:
                 *    rediskey      會過期
                 *    rediskey_01   不會過期
                 *    根據接收到過期的key,可以通過 key + _01 你儲存的標識
                 *    得到副key,然後就可以得到value值進行業務等操作,用完就可以刪除
                 */
                log.info("收到消失的key:" + message);

            }
            //__keyevent@0__:expired 為你的 redis 訂閱頻道名稱 預設一般是 0這個資料庫,分庫的後面在想想辦法吧
        }, "__keyevent@0__:expired");
    }


    /**
     * springboot專案啟動時跟著啟動
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        doTask();
    }
}

模擬執行測試

啟動專案

 redis有資料

 等到時間到了後,就會執行

 鍵空間通知就是這樣,主要還是這命令總忘記執行,還有另一種方法,就是配置conf檔案,省的每次重啟redis都要執行這程式碼

 config set notify-keyspace-events Ex 

2.通過 zset 資料

 目前還沒用到,後期業務上用到了在補充吧