redis键空间通知使用实现
最近在开发一个定时活动,而且活动是多个场次的。这个是后就需要在活动开始的时候推送信息给客户端,结束的时候也要推送一次。简单的设计方案就是将配置缓存在redis,然后每隔一秒就轮询reids,获取配置信息,然后判断是不是到活动开始或者结束的时间点,然后推送给客户端。
但是,这里会有一个问题,如果没有到活动开始或结束的时间点,这里会造成很多无用的轮询操作。这个操作不但增大了对这个key的访问量,同时也会占用cpu,降低机器性能。
redis在2.8.0版本提供了一个键空间通知功能机制,对于这个功能的详细描述,可以查阅官方文档。简单总结就是,客户端可以订阅一个key,当这个可以发生改变时,redis会通知到已经订阅的客户端。
实现这个实现也很简单,我们可以通过一个demo来看看如何使用这个机制。
package main
import (
context
fmt
github.com/go-redis/redis/v8
time
)
var redisCli *redis.Client
func init() {
// 连接redis
redisCli = redis.NewClient( redis.Options{
Addr: 127.0.0.1:6379 ,
Password: redis123 ,
})
}
/*
* redis key 过期自动通知
*/
func SetExpireEvent() {
// 设置一个键,并且3秒钟之后过期
redisCli.Set(context.Background(), test_expire_event_notify , 测试键值过期通知 , 3*time.Second)
}
func SubExpireEvent() {
// 订阅key过期事件
sub := redisCli2.Subscribe(context.Background(), __keyevent@0__:expired )
// 这里通过一个for循环监听redis-server发来的消息。
// 当客户端接收到redis-server发送的事件通知时,
// 客户端会通过一个channel告知我们。我们再根据
// msg的channel字段来判断是不是我们期望收到的消息,
// 然后再进行业务处理。
for {
msg := -sub.Channel()
fmt.Println( Channel , msg.Channel)
fmt.Println( pattern , msg.Pattern)
fmt.Println( pattern , msg.Payload)
fmt.Println( PayloadSlice , msg.PayloadSlice)
}
}
func main() {
SetExpireEvent()
go SubExpireEvent()
// 这里sleep是为了防止main方法直接推出
time.Sleep(10 * time.Second)
}
代码结果输出如下:
上面代码实现逻辑很简单,核心逻辑就是订阅__keyevent@0__:expired这个事件,然后一个循环等待事件的通知。值得注意的是,要启用这个特性需要修改配置文件,启用notify-keyspace-events这个配置,可以参考配置文件中的注释对不同事件进行启用。
在业务中使用回到开始提及的业务场景,如何在这种场景中使用redis的机制呢?其实很简单,当活动配置到数据库之后,会有一个更新缓存的步骤。在将数据设置在活动缓存时,只要我们计算当前时间到活动开始/结束这个时间差,将这个差作为键的过期时间。
例如,活动id1的开始时间为t0, 结束时间为t2, 当前时间为t。这个时候就可以这么设置:
// 活动开始的key设置 redisCli.Set(context.Background(), "id1:start", "活动开始了", t0 - t) // 活动结束结束的key设置 redisCli.Set(context.Background(), "id1:start", "活动开始了", t1 - t)
通过这么设置,当活动开启/结束就可以接收到相应的通知了。
总结这种方案其实可以完全满足文中的需求场景,但是这种方案其实也存在一些问题。其实这些问题在redis文档中也有相应说明。
第一,redis-server在推送这个事件通知时,只要订阅了这个事件的客户端端都会收到这个消息。通常,我们的业务都是跑在多个结点中,所以这个时候就要根据场景看要不要进行业务的原子操作。 第二,redis-server只会推送一次这个通知。假如说在redis-server推送这个通知时,结点挂了或者由于其他异常情况没有收到消息,redis-server不会再重新推送。 第三,通知可能会延迟。由于redis实现机制,对于过期的键,会有两种机制进行处理,一种是当命令访问键时,发现键已过期。另一种是通过后台系统在后台逐步查找过期的键,以便能够收集那些从未被访问的键。所以会有出现延迟的可能。本文介绍了使用redis的键空间通知机制来实现了一种业务场景,当然这种方式并不是最好的,还有其他方式来实现。在实际开发中会有很多的因素要考虑,而且实现方式也是多种多样,这个就需要我们分析每一种方案的利弊,然后进行抉择。
到此这篇关于redis键空间通知使用实现的文章就介绍到这了,更多相关redis键空间通知 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
我想要获取技术服务或软件
服务范围:MySQL、ORACLE、SQLSERVER、MongoDB、PostgreSQL 、程序问题
服务方式:远程服务、电话支持、现场服务,沟通指定方式服务
技术标签:数据恢复、安装配置、数据迁移、集群容灾、异常处理、其它问题
本站部分文章参考或来源于网络,如有侵权请联系站长。
数据库远程运维 redis键空间通知使用实现
相关文章
- 使用Redis缓存优化系统性能(redis缓存大小)
- 清理使用Java实现Redis数据过期清理(redisjava过期)
- Redis 实现高效的数据更新(redis数据更新)
- 极速操作:Redis实用工具类封装(redis工具类封装)
- 快速启动Redis服务器,让数据更有效率!(启动redis服务器)
- Redis:优化内存使用的利器(redis 内存使用)
- 如何让Redis缓存按计划过期(怎么让redis过期)
- 利用Redis优化网站性能的秘密(网站使用redis的作用)
- 实现高效提高性能Redis缓存技术实例(缓存技术redis实例)
- 统计Redis的QPS数据定位问题的关键突破口(统计redis的qps)
- Redis宣告终结一段结束的旅程(结束 redis)
- Redis瞬间并发失效面临严峻考验(瞬时并发redis失效)
- 使用Redis快速实现验证码功能(用redis实现验证码)
- 一键清空 Redis 所有键的简易办法(清除redis所有的键)
- 利用Redis实现数据转发链路的构建(数据转发 链接redis)
- 简单实现使用 Redis 存储数据字典(数据字典缓存redis)
- Redis实现持久性存储(持久层redis)
- 一起办公,同时使用多台Redis(一台电脑多个redis)
- SSM框架中使用Redis轻松实现高效数据存储(ssm中redis搭建)
- 使用Redis缓存优化分页列表查询(分页列表用redis缓存)
- 实现全局自增主键Redis 存储策略(全局自增主键redis)
- Redis队列实现批量处理(redis 队列 批量)
- Redis键空间事件灵活的分布式数据结构实现(redis键空间事件)
- Redis运维 实现数据可靠的应对方案(redis 运维场景)
- Redis实现快速输出所有存储数据(redis 输出所有数据)