一、說明
之前專案中一直使用ConcurrentLinkedQueue做為緩沖佇列(主要是單個專案內,單條改批量的場景,多個專案間使用的是rocketmq),雖然用著方便但是是純記憶體的,
如果專案發生例外崩潰記憶體佇列中的資料就會全部丟失(只能從日志中恢復),所以一直想找一個簡單高效支持持久化的嵌入式訊息佇列,中間用過activemq的嵌入模式,
雖然是支持持久化了,但是配置起來很繁瑣,用起來也不簡單,性能相比來說也不太行,
后來偶然發現了FQueue,專案地址:https://github.com/tietang/fqueue
看了看專案原始碼,純java撰寫,總共沒幾個類,完全可以改造成我想要的 簡單高效支持持久化的嵌入式訊息佇列,
二、改造
1、因為是要做成嵌入式的,所以memcached協議相關的代碼都洗掉了,
2、預創建檔案洗掉了,還有一些零零碎碎的改動,(好幾年了,記不清了),
3、相較于原代碼,改動最大的就是鎖的部分,FQueue 讀和寫使用的是同一把鎖,
我改成了讀和寫使用不同的鎖,只在檔案切換的時候使用同一把鎖,性能大概提示了百分之20左右(本來就很快,錦上添花),
4、添加了記憶體佇列,這個主要解決同一個機器創建了大量佇列(上千)時,佇列訊息消費較快,因為使用了記憶體映射磁盤(每隔10ms就會呼叫force()同步磁盤),
頻繁操作磁盤導致磁盤io過高的問題,默認情況下佇列大小超過50時才會寫入持久化佇列,可以在專案啟動時呼叫SMQ.setting(String dbPath, int logSize, int memoryQueueSize)
進行設定,
三、使用
1、說明
目前是集成在我個人的工具類專案中的,已發布到中央倉庫,專案地址:https://github.com/shenbururen/sun-utils
該專案強依賴hutool,算是個人對hutool的個性化的擴展,如果不想依賴該專案,只想單純的使用SMQ,可以將原始碼中 cn.sanenen.queue包復制出來,單獨使用,
2、maven參考
<!-- https://mvnrepository.com/artifact/cn.sanenen/sun-utils --> <dependency> <groupId>cn.sanenen</groupId> <artifactId>sun-utils</artifactId> <version>2.3.0</version> </dependency>
3、呼叫
SMQ使用時只有三個方法,向佇列放入資料、從佇列取出資料、獲取佇列大小(一般只在監控佇列是否積壓時使用,判斷佇列是否有資料,使用獲取佇列資料是否為null進行判斷),
我一般是寫一個單獨的類,通過靜態方法呼叫,
/** * 本地持久化記憶體佇列 */ public class MsgQueue { private static final String testDataTopic = "testData"; /** * 向佇列放入資料,支持多執行緒, */ public static void putTestData(TestData msg) { SMQ.push(testDataTopic, JSON.toJSONString(msg)); } /** * 從佇列取出資料,支持多執行緒, */ public static TestData getTestData() { String poll = SMQ.pop(testDataTopic); if (StrUtil.isNotBlank(poll)) { return JSON.parseObject(poll, TestData.class); } return null; } /** * 獲取佇列大小 */ public static long getTestDataSize(){ return SMQ.size(testDataTopic); } }
四、注意事項
1、默認會在專案目錄下生成一個smq的檔案夾用來存放佇列資料,同一個smq的檔案夾同時只可被一個專案使用,
2、SMQ.setting(String dbPath, int logSize, int memoryQueueSize)
dbPath檔案存盤目錄,默認是smq,會在專案目錄下創建一個smq的目錄,(還沒測驗過絕對路徑),
logSize屬性只可以在專案最開始時設定,之后不可以再設定不同的值,(也可以將生成的smq檔案夾洗掉后重新啟動進行設定),
memoryQueueSize是記憶體佇列大小,默認是50,佇列資料積壓超過memoryQueueSize后才會寫入持久化佇列,(目前memoryQueueSize為0時還是會創建記憶體佇列,這里之后會優化,不影響使用,)
專案使用了addShutdownHook,會在專案關閉時將記憶體佇列訊息寫入持久化佇列,結束專案時使用kill -15 不要用 -9,否則可能造成訊息丟失,
建議都使用默認的,也就是不要呼叫這個方法,避免呼叫出現問題,
3、最好使用在不是要求百分百訊息不丟失的場景,(在專案例外停止、服務器停電關機時,有概率丟失訊息,)
4、目前已經使用兩年多,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543741.html
標籤:其他
