redis java 监听_从零手写实现redis(四)添加监听器
前言
java從零手寫實(shí)現(xiàn)redis(一)如何實(shí)現(xiàn)固定大小的緩存?
java從零手寫實(shí)現(xiàn)redis(三)redis expire 過期原理
java從零手寫實(shí)現(xiàn)redis(三)內(nèi)存數(shù)據(jù)如何重啟不丟失?
本節(jié),讓我們來一起學(xué)習(xí)一下如何實(shí)現(xiàn)類似 guava-cache 中的 removeListener 刪除監(jiān)聽器,和類似 redis 中的慢日志監(jiān)控的 slowListener。
刪除監(jiān)聽器
說明
我們?cè)趦煞N場(chǎng)景下刪除數(shù)據(jù)是對(duì)用戶透明的:
(1)size 滿了之后,進(jìn)行數(shù)據(jù)淘汰。
(2)expire 過期時(shí),清除數(shù)據(jù)。
這兩個(gè)特性對(duì)用戶本來應(yīng)該是無感的,不過用戶如果關(guān)心的話,也可以通過添加刪除監(jiān)聽器來獲取到相關(guān)的變更信息。
實(shí)現(xiàn)思路
為了實(shí)現(xiàn)刪除的監(jiān)聽,我們需要找到刪除的位置,然后調(diào)用監(jiān)聽器即可。
evict 驅(qū)除的場(chǎng)景
每次 put 數(shù)據(jù)時(shí),都會(huì)校驗(yàn) size 是否達(dá)到最大的限制,如果達(dá)到,則進(jìn)行 evict 淘汰。
expire 過期的場(chǎng)景
用戶指定 expire 時(shí)間之后,回后臺(tái)異步執(zhí)行刷新。
也存在惰性刪除的場(chǎng)景。
接口定義
為了統(tǒng)一,我們將所有的刪除都定義統(tǒng)一的接口:
/*** 刪除監(jiān)聽器接口** @author binbin.hou* @since 0.0.6* @param <K> key* @param <V> value*/ public interface ICacheRemoveListener<K,V> {/*** 監(jiān)聽* @param context 上下文* @since 0.0.6*/void listen(final ICacheRemoveListenerContext<K,V> context);}內(nèi)置實(shí)現(xiàn)
系統(tǒng)內(nèi)置的實(shí)現(xiàn)如下:
public class CacheRemoveListener<K,V> implements ICacheRemoveListener<K,V> {private static final Log log = LogFactory.getLog(CacheRemoveListener.class);@Overridepublic void listen(ICacheRemoveListenerContext<K, V> context) {log.debug("Remove key: {}, value: {}, type: {}",context.key(), context.value(), context.type());}}這個(gè)監(jiān)聽器是默認(rèn)開啟的,暫時(shí)無法關(guān)閉。
自定義
用戶可以自己的需要,進(jìn)行自定義實(shí)現(xiàn):
public class MyRemoveListener<K,V> implements ICacheRemoveListener<K,V> {@Overridepublic void listen(ICacheRemoveListenerContext<K, V> context) {System.out.println("【刪除提示】可惡,我竟然被刪除了!" + context.key());}}測(cè)試
ICache<String, String> cache = CacheBs.<String,String>newInstance().size(1).addRemoveListener(new MyRemoveListener<String, String>()).build();cache.put("1", "1"); cache.put("2", "2");我們指定 cache 的大小為1,設(shè)置我們自定義的刪除監(jiān)聽器。
這里的刪除監(jiān)聽器可以添加多個(gè)。
日志
測(cè)試日志如下:
[DEBUG] [2020-09-30 19:32:54.617] [main] [c.g.h.c.c.s.l.r.CacheRemoveListener.listen] - Remove key: 2, value: 2, type: evict 【刪除提示】可惡,我竟然被刪除了!2慢操作監(jiān)聽器
說明
redis 中會(huì)存儲(chǔ)慢操作的相關(guān)日志信息,主要是由兩個(gè)參數(shù)構(gòu)成:
(1)slowlog-log-slower-than 預(yù)設(shè)閾值,它的單位是毫秒(1秒=1000000微秒)默認(rèn)值是10000
(2)slowlog-max-len 最多存儲(chǔ)多少條的慢日志記錄
不過 redis 是直接存儲(chǔ)到內(nèi)存中,而且有長(zhǎng)度限制。
根據(jù)實(shí)際工作體驗(yàn),如果我們可以添加慢日志的監(jiān)聽,然后有對(duì)應(yīng)的存儲(chǔ)或者報(bào)警,這樣更加方便問題的分析和快速反饋。
所以我們引入類似于刪除的監(jiān)聽器。
實(shí)現(xiàn)思路
我們處理所有的 cache 操作,并且記錄對(duì)應(yīng)的操作耗時(shí)。
如果耗時(shí)操作用戶設(shè)置的時(shí)間閾值,則調(diào)用慢操作監(jiān)聽器。
接口定義
為了保證接口的靈活性,每一個(gè)實(shí)現(xiàn)都可以定義自己的慢操作閾值,這樣便于分級(jí)處理。
比如超過 100ms,用戶可以選擇輸出 warn 日志;超過 1s,可能影響到業(yè)務(wù)了,可以直接接入報(bào)警系統(tǒng)。
public interface ICacheSlowListener {/*** 監(jiān)聽* @param context 上下文* @since 0.0.6*/void listen(final ICacheSlowListenerContext context);/*** 慢日志的閾值* @return 慢日志的閾值* @since 0.0.9*/long slowerThanMills();}自定義監(jiān)聽器
實(shí)現(xiàn)接口 ICacheSlowListener
這里每一個(gè)監(jiān)聽器都可以指定自己的慢日志閾值,便于分級(jí)處理。
public class MySlowListener implements ICacheSlowListener {@Overridepublic void listen(ICacheSlowListenerContext context) {System.out.println("【慢日志】name: " + context.methodName());}@Overridepublic long slowerThanMills() {return 0;}}使用
ICache<String, String> cache = CacheBs.<String,String>newInstance().addSlowListener(new MySlowListener()).build();cache.put("1", "2"); cache.get("1");- 測(cè)試效果
實(shí)際工作中,我們可以針對(duì)慢日志數(shù)據(jù)存儲(chǔ),便于后期分析。
也可以直接接入報(bào)警系統(tǒng),及時(shí)反饋問題。
小結(jié)
監(jiān)聽器實(shí)現(xiàn)起來比較簡(jiǎn)單,但是對(duì)于使用者的作用是比較大的。
文中主要講述了思路,實(shí)現(xiàn)部分因?yàn)槠拗?#xff0c;沒有全部貼出來。
開源地址:https://github.com/houbb/cache覺得本文對(duì)你有幫助的話,歡迎點(diǎn)贊評(píng)論收藏關(guān)注一波~
你的鼓勵(lì),是我最大的動(dòng)力~
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的redis java 监听_从零手写实现redis(四)添加监听器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cass直线连接快捷键(cass正交快捷
- 下一篇: java模拟登陆_java-模拟登陆练习