一、需求切入點
在公司做的乙個系統業務需要有個定時提醒的功能(資料在mysql中),要求提醒的時間差精準到分鐘
解決方案有:
使用定時器,每分鐘執行一次,查符合提醒的資料,發起提醒(資料庫連線與系統的負載都承受不住的!!)
將待提醒資料提前查出存進redis中,根據提醒時間設定過期時間,做redis的過期監聽,監聽到過期的資料再做業務處理(優點 : 不用實時查資料庫,一定程度上減少系統壓力 缺點: 一旦系統重啟或者系統出現異常,可能導致一些過期的資料沒有監聽到,造成資料沒有推送)
使用乙個延時佇列,利用redis的zset(sort set,有序不重複集合,關聯分數score進行排序),將提醒時間作為分數,提取符合條件的score對應的集合發起提醒(本文所述也是圍繞這個方案)
二、延時佇列的基本操作流程基本流程圖
**實現
生產者,只關心資料進佇列
public class messageprovider
} catch (exception e)
}/**
* 撤回訊息 業務延伸
* @param members
*/public void withdrawmessage(long members)
}
消費者,只關心需要消費的資料
// 從延伸佇列拉取符合消費的資料
listmsglist = delayingqueueservice.pull();
```msglist.stream().foreach(msg ->
```
延時佇列實現
public class delayingqueueservice
/*** 移除訊息
** @param queuemessage
* @return
*/@sneakythrows
public boolean remove(queuemessage queuemessage)
return remove > 0 ? true : false;
}/**
* 拉取最新需要
* 被消費的訊息
* rangebyscore 根據score範圍獲取 0-當前時間戳可以拉取當前時間及以前的需要被消費的訊息
** @return
*/public listpull()
msglist = strings.stream().map(msg -> catch (jsonprocessingexception e)
return message;
}).collect(collectors.tolist());
} catch (exception e)
return msglist;
}//獲得鎖
public boolean getlock()
public void releaselock()
}
三、結束語本文所述的方法也是存在一些小的缺點,比如,資料的正常操作依賴於第三方元件,如果redis掛掉了,這個服務就down掉了,實現延時佇列的方法有很多種,基於業務與系統本身的情況,相容利弊去做一些取捨,以達到最好的效果 關於redis中Zset元素的使用
zset在set基礎上增加了乙個排序 權值 需手動指定,分數越小,越排前面 zadd zadd name 序號 value 序號2 value2 依據序號的重要程度排序 zrange zrange name start end 查詢zset中的元素,預設從小到大排序,若要從大到小,使用zrevran...
使用redis中的zset實現實時排行榜
redis在業務開發中會被頻繁使用,zset是其中一種特殊用法,zset具排行榜的天然特性,我前幾個月在一次開發中使用到了zset,就是因為涉及到要實現乙個排行榜,那是我第一次用到zset,雖然之前都看過redis幾種資料型別的資料結構及其使用方法,但是真正用起來的時候,還是有一些細節的東西要處理的...
redis 六 redis的zset(有序集合)
相比於set,zset中會有乙個score屬性,用於set的排名。zadd 向zset中新增元素 sorce value zrem 刪除element zscore 獲取score zincrby 增加score zrange 獲取資料,start到end zrank 通過下標獲取排名 127.0....