前言

java从零手写实现redis(一)如何实现固定大小的缓存?

java从零手写实现redis(三)redis expire 过期原理

java从零手写实现redis(三)内存数据如何重启不丢失?

本节,让我们来一起学习一下如何实现类似 guava-cache 中的 removeListener 删除监听器,和类似 redis 中的慢日志监控的 slowListener。

删除监听器

说明

我们在两种场景下删除数据是对用户透明的:

(1)size 满了之后,进行数据淘汰。

(2)expire 过期时,清除数据。

这两个特性对用户本来应该是无感的,不过用户如果关心的话,也可以通过添加删除监听器来获取到相关的变更信息。

实现思路

为了实现删除的监听,我们需要找到删除的位置,然后调用监听器即可。

evict 驱除的场景

每次 put 数据时,都会校验 size 是否达到最大的限制,如果达到,则进行 evict 淘汰。

expire 过期的场景

用户指定 expire 时间之后,回后台异步执行刷新。

也存在惰性删除的场景。

接口定义

为了统一,我们将所有的删除都定义统一的接口:

/*** 删除监听器接口** @author binbin.hou* @since 0.0.6* @param <K> key* @param <V> value*/
public interface ICacheRemoveListener<K,V> {/*** 监听* @param context 上下文* @since 0.0.6*/void listen(final ICacheRemoveListenerContext<K,V> context);}

内置实现

系统内置的实现如下:

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());}}

这个监听器是默认开启的,暂时无法关闭。

自定义

用户可以自己的需要,进行自定义实现:

public class MyRemoveListener<K,V> implements ICacheRemoveListener<K,V> {@Overridepublic void listen(ICacheRemoveListenerContext<K, V> context) {System.out.println("【删除提示】可恶,我竟然被删除了!" + context.key());}}

测试

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,设置我们自定义的删除监听器。

这里的删除监听器可以添加多个。

日志

测试日志如下:

[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

慢操作监听器

说明

redis 中会存储慢操作的相关日志信息,主要是由两个参数构成:

(1)slowlog-log-slower-than 预设阈值,它的单位是毫秒(1秒=1000000微秒)默认值是10000

(2)slowlog-max-len 最多存储多少条的慢日志记录

不过 redis 是直接存储到内存中,而且有长度限制。

根据实际工作体验,如果我们可以添加慢日志的监听,然后有对应的存储或者报警,这样更加方便问题的分析和快速反馈。

所以我们引入类似于删除的监听器。

实现思路

我们处理所有的 cache 操作,并且记录对应的操作耗时。

如果耗时操作用户设置的时间阈值,则调用慢操作监听器。

接口定义

为了保证接口的灵活性,每一个实现都可以定义自己的慢操作阈值,这样便于分级处理。

比如超过 100ms,用户可以选择输出 warn 日志;超过 1s,可能影响到业务了,可以直接接入报警系统。

public interface ICacheSlowListener {/*** 监听* @param context 上下文* @since 0.0.6*/void listen(final ICacheSlowListenerContext context);/*** 慢日志的阈值* @return 慢日志的阈值* @since 0.0.9*/long slowerThanMills();}

自定义监听器

实现接口 ICacheSlowListener

这里每一个监听器都可以指定自己的慢日志阈值,便于分级处理。

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");

  • 测试效果
[DEBUG] [2020-09-30 17:40:11.547] [main] [c.g.h.c.c.s.i.c.CacheInterceptorCost.before] - Cost start, method: put
[DEBUG] [2020-09-30 17:40:11.551] [main] [c.g.h.c.c.s.i.c.CacheInterceptorCost.after] - Cost end, method: put, cost: 10ms
【慢日志】name: put
[DEBUG] [2020-09-30 17:40:11.554] [main] [c.g.h.c.c.s.i.c.CacheInterceptorCost.before] - Cost start, method: get
[DEBUG] [2020-09-30 17:40:11.554] [main] [c.g.h.c.c.s.i.c.CacheInterceptorCost.after] - Cost end, method: get, cost: 1ms
【慢日志】name: get

实际工作中,我们可以针对慢日志数据存储,便于后期分析。

也可以直接接入报警系统,及时反馈问题。

小结

监听器实现起来比较简单,但是对于使用者的作用是比较大的。

文中主要讲述了思路,实现部分因为篇幅限制,没有全部贴出来。

开源地址:https://github.com/houbb/cache

觉得本文对你有帮助的话,欢迎点赞评论收藏关注一波~

你的鼓励,是我最大的动力~

redis java 监听_从零手写实现redis(四)添加监听器相关推荐

  1. protools监听_给新手写的万元录音设备选择2020系列(六)监听音箱/耳机

    又到了我最爱的挑音箱环节,这次我还加上了两款实测好用的耳机.和2017版一样,音箱/耳机文章预计仍然是业余用户和自封专业用户的重度聚集区,各种不靠谱言论和私信满天飞.这种带有明显主观判断.情绪化.无训 ...

  2. java监听表变化_「Java Web开发」Filte(过滤器)、Listener(监听器)

    过滤器简介: Filter(过滤器)是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对Web服务器管理的所有Web资源:例如Jsp.Servlet.静态图片文件或静态html文 ...

  3. SpringBoot监听redis订阅监听和发布订阅

    前言 我们可以在redis中发布一条订阅到通道中,所有监听了这个通道的都可以收到这个发布的内容! redis订阅监听配置类 代码如下: RedisListenerConfig.java package ...

  4. java 监听控制台输入

    分享一下我写的java监听控制台输入并可以给出响应的功能. 很多时候需要监听控制台的输入内容,相当于信号监听,根据输入的内容做出相应的动作,这里给出我的一个简单实现. 要注意的是:监听得到的消息中前后 ...

  5. Java监听mysql的binlog详解(mysql-binlog-connector)

    Java监听mysql的binlog详解(mysql-binlog-connector) 1. 需求概述 2. 技术选型 3. 方案设计 3.环境准备 3.1 查看是否开启binlog 3.2 mys ...

  6. java swing列表数据加监听,【Java Swing公开课|Java监听列表项选择事件怎么用,看完这篇文章你一定就会了】- 环球网校...

    [摘要]作为一门面向对象编程语言,Java吸收了C++语言的优点,也展现了其强大的一面,我们能在各个地方看到其功能强大和简单易用的两个特征,当然,也吸引了很多程序员的注意力,所以就有人想了解Java的 ...

  7. php 监听redis,php监听redis key失效触发回调事件_后端开发

    php中使用fsockopen实现异步请求(代码示例)_后端开发 php执行一段程序,有可能几毫秒就执行完毕,也有可能耗时较长.例如,用户下单这个事件,如果调用了些第三方服务进行发邮件.短信.推送等通 ...

  8. java监听变量的变化_[Java学习小记]使用PropertyChangeSupport来监听变量的变化

    最近开始要着手写一个web项目 ,之前没怎么 写过Java ,所以觉得蛮有必要把每天学习到的一些知识点或者解决的一些问题给记录下来 .一来供自己在整理过程中掌握巩固,二来也为以后再次出现该问题时能快速 ...

  9. java bean 监听_事件监听器?将JavaBeans接通起来的方法

    摘 要 JavaBeans 通 过 事 件( 封 装 着 与 所 发 生 情 况 有 关 的 数 据 的 对 象) 与 其 它 软 件 组 件 进 行 通 讯. 本 文 将 向 你 展 示 如 何 利 ...

最新文章

  1. C++primer 10.6节练习
  2. stl algorithm清单
  3. [转]Nokia是否还有未来 - 小议诺基亚和微软的战略布局
  4. mysql insert慢_MySQL insert语句慢查询的优化
  5. (Eclipse打包问题)Export aborted because fatal lint er
  6. 反调试技术揭秘(转)
  7. springcloud Hystrix Dashboard微服务监控
  8. 排序算法-----冒泡排序和选择排序
  9. 安卓IPCamera-ONVIF JAVA代码开源啦
  10. 随机效应估算与固定效应估算_纯电动汽车的电池价格,可以怎么估算?
  11. 计算机房空调设计规范,空调机房防火设计规范
  12. kettle安装教程
  13. STM32F407 USB CDC调试与经验总结
  14. 大数据的十大应用领域
  15. 百度网盘不限速下载10M/S
  16. python io多路复用_【python】-- IO多路复用(select、poll、epoll)介绍及实现
  17. 转:用迅雷下载Android SDK全系列
  18. 解决每次新建word都有页眉和页脚
  19. 写个.net开发者的Linux迁移指南
  20. 中望3D 2022 基准平面

热门文章

  1. jboss调jvm参数_在同一台机器上启动多个JBoss A-MQ JVM
  2. jsr 269 api_研究Java 9 Money and Currency API(JSR 354)
  3. JPA @Embeddable和@Embedded
  4. java 文件流读取文本_如何在Java 8中处理流和读取文本文件
  5. activemq 实例_在一台计算机上运行多个ActiveMQ实例
  6. jvm 内存镜像_镜像镜像–使用反射在运行时查看JVM内部
  7. Java技巧:创建监视友好的ExecutorService
  8. Picocli 2.0:类固醇上的Groovy脚本
  9. 异步过程的自动化测试
  10. 线程并发库和线程池的作用_并发–顺序线程和原始线程