1. 程式人生 > >基於redis的延遲消息隊列設計

基於redis的延遲消息隊列設計

redis

需求背景

  • 用戶下訂單成功之後隔20分鐘給用戶發送上門服務通知短信
  • 訂單完成一個小時之後通知用戶對上門服務進行評價
  • 業務執行失敗之後隔10分鐘重試一次

    類似的場景比較多 簡單的處理方式就是使用定時任務 假如數據比較多的時候 有的數據可能延遲比較嚴重,而且越來越多的定時業務導致任務調度很繁瑣不好管理。

隊列設計

目前可以考慮使用rabbitmq來滿足需求 但是不打算使用,因為目前太多的業務使用了另外的MQ中間件。

開發前需要考慮的問題?

  • 及時性 消費端能按時收到
  • 同一時間消息的消費權重
  • 可靠性 消息不能出現沒有被消費掉的情況
  • 可恢復 假如有其他情況 導致消息系統不可用了 至少能保證數據可以恢復
  • 可撤回 因為是延遲消息 沒有到執行時間的消息支持可以取消消費
  • 高可用 多實例 這裏指HA/主備模式並不是多實例同時一起工作
  • 消費端如何消費

    當然初步選用redis作為數據緩存的主要原因是因為redis自身支持zset的數據結構(score 延遲時間毫秒) 這樣就少了排序的煩惱而且性能還很高,正好我們的需求就是按時間維度去判定執行的順序 同時也支持map list數據結構。

簡單定義一個消息數據結構

private String topic;/***topic**/ private String id;/***自動生成 全局惟一 snowflake**/ private String bizKey; private long delay;/***延時毫秒數**/ private int priority;//優先級 private long ttl;/**消費端消費的ttl**/
private String body;/***消息體**/ private long createTime=System.currentTimeMillis(); private int status= Status.WaitPut.ordinal();

運行原理:

  1. 用Map來存儲元數據。id作為key,整個消息結構序列化(json/…)之後作為value,放入元消息池中。
  2. 將id放入其中(有N個)一個zset有序列表中,以createTime+delay+priority作為score。修改狀態為正在延遲中
  3. 使用timer實時監控zset有序列表中top 10的數據 。 如果數據score>=當前時間毫秒就取出來,根據topic重新放入一個新的可消費列表(list)中,在zset中刪除已經取出來的數據,並修改狀態為待消費
  4. 客戶端獲取數據只需要從可消費隊列中獲取就可以了。並且狀態必須為待消費 運行時間需要<=當前時間的 如果不滿足 重新放入zset列表中,修改狀態為正在延遲。如果滿足修改狀態為已消費。或者直接刪除元數據。

客戶端

因為涉及到不同程序語言的問題,所以當前默認支持http訪問方式。

  1. 添加延時消息添加成功之後返回消費唯一ID POST /push {…..消息體}
  2. 刪除延時消息 需要傳遞消息ID GET /delete?id=
  3. 恢復延時消息 GET /reStore?expire=true|false expire是否恢復已過期未執行的消息。
  4. 恢復單個延時消息 需要傳遞消息ID GET /reStore/id
  5. 獲取消息 需要長連接 GET /get/topic

用nginx暴露服務,配置為輪詢 在添加延遲消息的時候就可以流量平均分配。

目前系統中客戶端並沒有采用HTTP長連接的方式來消費消息,而是采用MQ的方式來消費數據這樣客戶端就可以不用關心延遲消息隊列。只需要在發送MQ的時候攔截一下 如果是延遲消息就用延遲消息系統處理。

消息可恢復

實現恢復的原理 正常情況下一般都是記錄日誌,比如mysql的binlog等。

這裏我們直接采用mysql數據庫作為記錄日誌。

目前打算創建以下2張表:

  1. 消息表 字段包括整個消息體
  2. 消息流轉表 字段包括消息ID、變更狀態、變更時間、zset掃描線程Name、host/ip

定義zset掃描線程Name是為了更清楚的看到消息被分發到具體哪個zset中。前提是zset的key和監控zset的線程名稱要有點關系 這裏也可以是zset key。

舉個栗子

假如redis服務器宕機了,重啟之後發現數據也沒有了。所以這個恢復是很有必要的,只需要從表1也就是消息表中把消息狀態不等於已消費的數據全部重新分發到延遲隊列中去,然後同步一下狀態就可以了。

當然恢復單個任務也可以這麽幹。

關於高可用

分布式協調還是選用zookeeper吧。

如果有多個實例最多同時只能有1個實例工作 這樣就避免了分布式競爭鎖帶來的壞處,當然如果業務需要多個實例同時工作也是支持的,也就是一個消息最多只能有1個實例處理,可以選用zookeeper或者redis就能實現分布式鎖了。

最終做了一下測試多實例同時運行,可能因為會涉及到鎖的問題性能有所下降,反而單機效果很好。所以比較推薦基於docker的主備部署模式。

擴展

支持zset隊列個數可配置 避免大數據帶來高延遲的問題。

目前存在日誌和redis元數據有可能不一致的問題 如mysql掛了,寫日誌不會成功。

設計圖:


官網 http://www.fhadmin.org/
A代碼編輯器,在線模版編輯,仿開發工具編輯器,pdf在線預覽,文件轉換編碼
B 集成代碼生成器 [正反雙向](單表、主表、明細表、樹形表,快速開發利器)+快速表單構建器
freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表sql腳本,處理類,service等完整模塊
C 集成阿裏巴巴數據庫連接池druid 數據庫連接池 阿裏巴巴的 druid。Druid在監控、可擴展性、穩定性和性能方面都有明顯的優勢
D 集成安全權限框架shiro
Shiro 是一個用 Java 語言實現的框架,通過一個簡單易用的 API 提供身份驗證和授權,更安全,更可靠
E 集成ehcache 分布式緩存
是一個純Java的進程內緩存框架,具有快速、精幹等特點,廣泛使用的開源Java分布式緩存。
F 集成微信接口開發,微信自定義菜單(支持多個公眾號)
G 圖片爬蟲技術:輸入有圖片的網址,能把此網頁的圖片爬取並下載到本地服務器
H SQL 編輯器, 支持復雜sql語句(寫入語句,查詢語句),生成報表,可以導出excel
I websocket 真正及時通訊技術
即時聊天、及時站內信並聲音提醒、實時在線管理、websocket及時刷新頁面(完勝ajax技術
J redis 工具類接口,方便調用,並發能力強
K 多數據源(支持同時連接無數個數據庫,可以不同的模塊連接不同數的據庫)支持N個數據源
L 快遞單號物流查詢接口(不需要選擇物流公司,根據單號自動識別)

M 調用攝像頭拍照,自定義裁剪編輯頭像,頭像圖片色度調節
1. 權限管理:點開二級菜單進入三級菜單顯示 角色(基礎權限)和按鈕權限
角色(基礎權限): 分角色組和角色,獨立分配菜單權限和增刪改查權限。
按鈕權限: 給角色分配按鈕權限。
2. 按鈕管理:自定義按鈕管理,維護按鈕權限標識等
3. 菜單管理:無限級別自定義菜單,自定義菜單圖標,業務菜單和系統菜單分離,菜單狀態顯示隱藏(遞歸處理
4. 數據字典:無限級別,支持多級別無限分類。內設編號,排序等
5. 日誌管理:記錄用戶登錄退出和一些重要操作記錄
6. 在線管理:websocket技術,實時檢測在線用戶列表,統計在線人數,可強制用戶下線 同一用戶只能在一個客戶端登錄
7. 系統用戶:對各個基本的用戶增刪改查,單發、群發站內信郵件短信,導入導出excel表格,批量刪除
8. 會員管理:對前臺用戶管理,分配會員級別,到期時間,狀態,聯系信息等資料
9. 代碼生成:生成完整的模塊代碼,並保留生成記錄模版,可復用 (超強悍開發利器
正向生成: 生成完整的模塊,頁面、處理類、service層、myabaits的xml 建表的sql腳本等
反向生成: 任意連接其它數據庫(mysql、oracle、sqlserver),根據表反射生成本系統的模塊

模版管理:代碼在線編輯器,管理模版,保存編輯記錄,一鍵還原,代碼生成器如虎添翼
10. 性能監控:監控整個系統的性能,SQL監控,SQL防火墻,URL監控,SPRING監控,SESSION監控等
11. 接口測試:POST or GET 方式檢測系統接口,參數加密,json返回結果,計算服務器響應時間
12. 發送郵件:單發,群發郵件
13. 置二維碼:生成二維碼圖表保存到服務器 or 解析讀取二維碼內信息
14. 圖表報表:柱狀圖、餅狀圖、折線圖、各種圖表大全
15. 地圖工具:打開地圖, 鼠標點擊地圖某位置獲取經緯度坐標,根據經緯度計算兩點距離
16. 打印測試:頁面打印預覽測試
17. 圖片管理:對批量上傳的圖片統一管理 ,點擊放大,可打開多個,自由切換,絢麗預覽效果
18. 圖片爬蟲:輸入某網址,爬出其圖片顯示在頁面上,可以放大預覽。可保存到服務器上,到圖片管理裏面
19. 站內信:收信箱和發信箱, websocket技術通訊技術做的及時收信提醒,可配置語音提示來信
20. 下拉聯動:四級下拉聯動demo
21. 系統設置:修改系統名稱,郵件服務器配置,短信賬號設置,圖片水印配置,微信配置
22. 及時聊天:打開聊天窗口,可群聊、一對一聊天
23. 表單構建:拖拽式快速自定義構建表單,組建元素豐富,有富文本、上傳控件、下拉框等等
24. 主附結構:提供一個主表和明細表模塊的例子(用本代碼生成器生成的)
25. 組織機構:無限級別,公司or部門管理
26. 員工管理:和組織機構部門管理,可以綁定登錄系統用戶,授權數據權限
27. 文件管理:上傳文件,修改刪除文件,計算文件大小
28. 快遞查詢:輸入快遞單號,查詢物流跟蹤信息。不需要選擇物流公司,根據單號自動識別
-------------------------------------------------------------------------------------------------------------------------數據庫管理
29. 數據庫備份:可備份單表、整庫,支持本地和遠程數據庫備份(java界面編程技術,socket編程技術)
30. 備份定時器:quartz 2.2 強大的任務調度,多線程備份數據庫,任務啟動關閉異步操作
31. 數據庫還原:歷史備份記錄,還原數據庫 or 單表 ,統計備份時間和文件大小
32. SQL編輯器:強大的SQL編輯器,支持編輯語句復雜查詢語句,生成動態報表,可導出excel
------------------------------------------------------------------------------微信模塊 有指導視頻 花生殼本地IP映射操作
33. 公眾號管理:維護多公眾號信息,配置appid和appsecret 支持微信自定義菜單
34. 關註回復:微信用戶關註公眾號回復
35. 文本回復:匹配關鍵詞進行文本回復
36. 圖文回復:匹配關鍵詞進行圖文回復
37. 應用命令:匹配關鍵詞進行命令操作,例如微信發送命令,執行服務器重啟、關機、鎖定等操作

菜單權限:分配給每個角色不同的菜單權限, 每個角色看到的菜單不同,無限級別菜單
按鈕權限:獨立分配不同的角色不同的功能權限,增刪改查權限分配具體到不同的菜單,自定義按鈕管理
支持多用戶分權限管理後臺, 權限具體到不同的菜單不同的按鈕
新聞管理:新聞的維護、發布、權重排序等 采用百度ueditor富文本框
公告管理:公告的維護、發布
廣告管理:廣告的維護、發布,狀態維護,上傳廣告圖片
友情鏈接:友情鏈接的維護、狀態維護
特別推薦:特別推薦、狀態維護

技術點

1. 導出 導入 excel 文件
2 導出word文件
3. IO 流上傳下載文件
4. 群發郵件,可以發html、純文本格式,可以發給任意郵箱(實現批量發送廣告郵件)
5. 群發or單獨 發送短信,支持兩種第三方短信商接口
6. spring aop 事務處理
7. 代碼生成器 (freemarker), 代碼 zip 壓縮打包
8. MD5加密 SHA加密(登錄密碼用此加密)接口加密身份校驗
9. 數據庫連接池 阿裏的 druid。Druid在監控、可擴展性、穩定性和性能方面都有明顯的優勢,支持並發
10.加入安全框架 shiro (登錄授權)(session管理)
11.根據漢字 解析漢字的全拼(拼音)和首字母(導入excel到用戶表,根據用戶的漢字姓名生成拼音的用戶名)
12.app接口@ResponseBody(支持與其它語言數據交互)
13.極光推送 (推送給APP及時消息,APP不啟動也能收到)
14.微信接口(身份驗證,文本、圖文回復等) 微信遠程控制服務器重啟、鎖定、其它應用程序
15.java Quartz2.2 任務調度
16.java websocket 即時通訊技術,點對點,群聊,單聊
17.Lucene全文檢索(在贈送的項目中)
18.Base64傳輸圖片
19.圖片加水印(圖片水印,文字水印)
20.生成 or 解析 二維碼
21.HTML5 + JAVAEE WebSocket 通信技術,WebSocket 驗證用戶登錄,強制某用戶下線
22.批量異步上傳圖片,可預覽,有進度條,支持拖拽上傳(百度webuploader )。列表動態滑動放大展示。
23.ehcache 自定義二級緩存 ,選擇緩存存放目錄,處理並發,增加系統性能
24.服務器內部GET POST 請求
25.uploadify 上傳插件,單條、批量上傳多線程,帶進度條,異步,圖片、視頻, 其它文件格式均可上傳
26.地圖選點獲取經緯度坐標,根據倆經緯度計算距離
27.tab標簽頁面功能,標簽自由切換,不重復操作數據庫
28.站內信語音提醒,js控制音頻播放
29.百度富文本編輯器,可上傳圖片
30.網頁爬蟲技術,可根據網頁地址爬取圖片和網頁標題等信息(爬取某商城圖片保存本服務器)
31.redis 技術
32.多數據源技術
33.springmvc 下拉多級聯動技術
34.調用攝像頭拍照技術,圖片裁剪技術
35.快遞接口查詢技術,輸入快遞單號查詢物流信息
36.在線編輯器,仿開發工具
37.pdf文件在線預覽,在線預覽文本文件,轉碼預覽








基於redis的延遲消息隊列設計