Redis 键空间事件通知
出处: 使用Redis完成定时任务
场景
使用Java做过项目的人大概都用过定时器。一般来说,项目里订单模块和评论模块,都会涉及到定时任务执行。比如说:
- 用户下订单后,需要在5分钟内完成支付,否则订单关闭;
- 用户在完成订单后,如果没有评论,过一星期,系统自动评论,并完结。
我以前曾经做过一个租车系统,其中订单的预约逻辑是这样的:
- 用户选择车辆并预约
- 后台系统开始计时
- 计时结束后,如果用户没有进行支付,则取消本次订单
当时后台计时部分的技术,用的就是java中的定时器类Timer ,使用schedule来设置定时任务。虽然说功能实现了,但还是有很多问题,因为Timer本质上还是启动了一个线程来进行处理。当预约用户过多时,系统内存就会飙升,而且当发布新功能时,如果重启服务器,所有的定时器都会丢失。
解决思路
薛定谔解决法
在订单信息中,加入过期时间,当用户查询订单或其他操作时,检查一下有没有过期的预订单,如果有,则进入逻辑处理。也就是说,当用户不进行操作时,这个预订单是不会自己结束的。这样做的好处在于,当系统重启时,这个订单的状态是不会收到影响的。坏处当然也显而易见,延迟率太高,主动权完全决定在用户手中。
轮询法
同样的,在订单信息中加入过期时间,后台启动一个定时线程,每隔一段时间遍历一次订单信息,如果有到期的,则结束订单。这种方法同样会影响系统性能。
使用Redis定时器解决
Redis定时器
Redis中有一个expire命令,用来设置key的过期时间。使用发布订阅,可以接收到key的过期提醒,当key过期时,再执行取消订单的逻辑,就可以了。
redis 定时器演示
1 |
127.0.0.1:6379> set test tom EX 10 |
设置test(key)的过期时间为10秒,10秒过后key自动销毁。
当然,仅仅有定时器还是不够的,接下来看redis的另一个功能,发布订阅。
Redis发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
用一张图来展示频道(channel1)与订阅者(client2, client5, client1)的关系:

当有消息发布时,他们的关系:

消息经由频道广播到每个订阅者中。
发布订阅演示:
首先创建一个频道:
1 |
127.0.0.1:6379> SUBSCRIBE chat1 |
此时控制台进入阻塞状态。
开启2个控制台,分别订阅chat1频道
1 |
127.0.0.1:6379> PSUBSCRIBE chat1 |
这两个控制台也依次进入阻塞状态。
再开一个控制台,进行信息的发布:
1 |
127.0.0.1:6379> PUBLISH chat1 "hello everyone!" |
此时两个订阅者和一个频道创建者都分别收到了相同的内容 hello everyone!
这里放上一张图片,效果可能会比较好:
发消息之前

发消息之后

redis的key过期通知也是基于发布订阅模型的。不同的是订阅频道是固定的__keyevent@0__:expired,当然,redis还有好多类似与这种特定频道的通知,想了解更多,可以看这里Redis键空间通知。
Redis过期通知
要使用Redis的过期通知功能,需要首先开启该功能 (2.8.0及以上的版本才有此功能)。
在配置文件中加入如下语句:
1 |
notify-keyspace-events Ex |
控制台1订阅频道__keyevent@0__:expired
1 |
127.0.0.1:6379> PSUBSCRIBE __keyevent@0__:expired |
控制台2存入一个key,并设置过期时间
1 |
127.0.0.1:6379> set test tom EX 10 |
当10秒过后,控制台1收到信息
1 |
1) "pmessage" |
使用springboot接收Redis过期通知
首先在maven中配置redis
1 |
<dependency> |
这个包是spring实现的redis client功能的包。
在springboot配置文件中配置redis
1 |
#Redis配置 |
代码实现
首先写接收通知的处理方法
1 |
@Component |
再写频道订阅的代码:
1 |
@Configuration |
这样整个代码就完成了。我们来测试一下效果:
使用控制台,新增一个key,并设置过期时间为10秒
1 |
127.0.0.1:6379> set testnofity xxx EX 10 |
切换到我们的程序中,可以在控制台看到如下信息:

好了,现在我们就可以根据不同的key做不同的业务逻辑处理了。比如规定,所有订单的key,都必须以order-订单号的形式存入,这样,当接收到订单过期的通知时,就可以解析出订单信息,进一步处理了。
当然,这个只是一种解决思路,你也可以使用一些其他的方式实现,比如说使用RabbitMQ消息队列实现。
Redis 键空间事件通知的更多相关文章
- python中的Redis键空间通知(过期回调)
介绍 Redis是一个内存数据结构存储库,用于缓存,高速数据摄取,处理消息队列,分布式锁定等等. 使用Redis优于其他内存存储的优点是Redis提供持久性和数据结构,如列表,集合,有序集和散列. 在 ...
- Redis键空间通知(keyspace notification),事件订阅
Redis键空间通知(keyspace notification),事件订阅 应用场景:有效期优惠券.24小时内支付.下单有效事件等等. 功能概览 键空间通知使得客户端可以通过订阅频道或模式, ...
- Redis 键空间通知
[Redis 键空间通知] 键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis 数据集的事件. 以下是一些键空间通知发送的事件的例子: 所有修改键的命令. 所有接收到 ...
- redis键空间通知(keyspace notification)
一.需求 在redis中,设置好key和生存时间之后,希望key过期被删除时能够及时的发送一个通知告诉我key,以便我做后续的一些操作. 二.环境 系统:windows10 php:7.1 redis ...
- Redis源码解析:09redis数据库实现(键值对操作、键超时功能、键空间通知)
本章对Redis服务器的数据库实现进行介绍,说明Redis数据库相关操作的实现,包括数据库中键值对的添加.删除.查看.更新等操作的实现:客户端切换数据库的实现:键超时相关功能的实现.键空间事件通知等. ...
- 利用Redis keyspace notification(键空间通知)实现过期提醒
一.序言: 本文所说的定时任务或者说计划任务并不是很多人想象中的那样,比如说每天凌晨三点自动运行起来跑一个脚本.这种都已经烂大街了,随便一个 Crontab 就能搞定了. 这里所说的定时任务可以说是计 ...
- 10Redis键空间通知(keyspace notifications)
Redis的键空间通知(keyspace notifications)功能是自2.8.0版本开始加入的,客户端可以通过订阅/发布(Pub/Sub)机制,接收那些以某种方式改变了Redis数据空间的事件 ...
- springboot使用Redis,监听Redis键过期的事件设置与使用代码
我使用的是Windows下的Redis服务,所以一下Redis设置都是在Windows平台进行. 1.修改Redis配置文件 1.1:Windows下的Redis存在两个配置文件 修改带有servic ...
- Redis事件通知示例
1. redis如同zk一样,提供了事件监听(或者说是回调机制), 下面是redis的配置说明: ############################# EVENT NOTIFICATION ## ...
随机推荐
- Codeforces 601B. Lipshitz Sequence(单调栈)
Codeforces 601B. Lipshitz Sequence 题意:,q个询问,每次询问给出l,r,求a数组[l,r]中所有子区间的L值的和. 思路:首先要观察到,斜率最大值只会出现在相邻两点 ...
- axios 是如何封装 HTTP 请求的
原载于 TutorialDocs 网站的文章<How to Implement an HTTP Request Library with Axios>.译者:zhangbao90shttp ...
- go面试
**1**.简述golang中make和new的区别 make用于内建类型(只能用于创建map.slice 和channel)的内存分配.并且返回一个有初始值(非零)的T类型,而不是*T. new用于 ...
- shell [ ] 和 [[ ]] 区别
[参考文章]:shell if [[ ]]和[ ]区别 || && [参考文章]:Shell test 命令 1. [ ] 和 test test 等同于 [ ] 可用于判断某个条件 ...
- docker crontab踩坑记录
环境,docker centos7.4 容器启动时注意两点 入口要设置/usr/sbin/init,并且配置主机完全访问权限(--privileged) (否则执行service的时候会出现Faile ...
- LeetCode 10. 正则表达式匹配(Regular Expression Matching)
题目描述 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或多个前面的元素. 匹配应该覆盖整个字符串 (s ...
- SpringMVC和AJAX交互
在实际开发中我们经常需要前后台交互,那么springmvc与ajax之间交互这里记录下在实际开发中遇到的细节问题. jsp页面: <fieldset id="login" s ...
- 自动化测试 | 好用的自动化测试工具Top 10
欲善其事必先利其器,本文从软件测试人员痛点出发,介绍如何先从工具选择上取得优势,在有限的时间内完成工作.经常有人在公众号留言或是后台咨询,做自动化测试用哪个工具好,或是学哪门编程语言好呢? 这个时候总 ...
- linux下如何单独编译设备树?
答: make <vendor>/<device_name>.dtb 如: make freescale/fsl-1043a-rdb.dtb
- Nginx优化之服务性能优化
优化Nginx服务的worker进程个数 修改nginx主配置文件 worker_processes 1; #指定了Nginx要开启的进程数,结尾数字就是进程个数 Nginx有Master进程和wor ...