最近在开发一个定时活动,而且活动是多个场次的。这个是后就需要在活动开始的时候推送信息给客户端,结束的时候也要推送一次。简单的设计方案就是将配置缓存在redis,然后每隔一秒就轮询reids,获取配置信息,然后判断是不是到活动开始或者结束的时间点,然后推送给客户端。

但是,这里会有一个问题,如果没有到活动开始或结束的时间点,这里会造成很多无用的轮询操作。这个操作不但增大了对这个key的访问量,同时也会占用cpu,降低机器性能。
redis在2.8.0版本提供了一个键空间通知功能机制,对于这个功能的详细描述,可以查阅官方文档。简单总结就是,客户端可以订阅一个key,当这个可以发生改变时,redis会通知到已经订阅的客户端。

实现

这个实现也很简单,我们可以通过一个demo来看看如何使用这个机制。

package mainimport ("context""fmt""github.com/go-redis/redis/v8""time"
)var redisCli *redis.Clientfunc init() {// 连接redisredisCli = 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键空间通知相关推荐

  1. Redis键空间通知(Keyspace Notifications)

    Redis Keyspace Notifications https://redis.io/topics/notifications Redis 是一个键值对数据库服务器,服务器中每个数据库都由 re ...

  2. 集群空间服务器接收不到消息,解决Redis集群条件下键空间通知服务器接收不到消息的问题...

    解决Redis集群条件下键空间通知服务器接收不到消息的问题 键空间通知介绍 键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis 数据集的事件. 可以通过对redis的 ...

  3. 键空间通知(keyspace notification)

    Redis键空间通知(keyspace notification) 本文档翻译自: http://redis.io/topics/notifications . 键空间通知功能目前仍在开发中,这个文档 ...

  4. 手动计算机键,大神教你把电脑设置每天自动开机,从此以后再也不用手动按电源键了!...

    为了让自己的办公桌面更加的整洁干净,很多朋友都会在桌上放置一个置物架,把笔记本电脑塞到这个置物架底下,在上面放一个显示器,这样的话桌面就会瞬间变得整洁很多.不过这有一个缺点,那就是每天早上来上班的时候 ...

  5. 文章如何做伪原创 SEO大神教你几招做原创网站文章的心得

    想要创作出好的文章并被百度所喜欢,就非常需要SEO的优化能力,以及要对文章进行塬创或伪塬创,那么,如何做伪塬创文章?以及如何做好塬创网站文章呢?对此,本文小编就为大家带来了几招做"塬创&qu ...

  6. mc服务器出生地修改,《我的世界》MC出生地太坑爹怎么办?大神教你一个指令就搞定了!...

    <我的世界>MC出生地太坑爹怎么办?大神教你一个指令就搞定了!在沙盒游戏<我的世界>里面,玩家们刚开始进入游戏的地方就是出生地,又叫做出生点.这些出生地是系统随机安排生成的地方 ...

  7. win7如何开启无线网卡服务器,大神教你win7无线网卡怎么设置wifi

    wifi上网已经风靡全世界,可是电脑开启wifi是需要无线网卡的,那么win7无线网卡怎么设置wifi呢?这就有点深度了,大家都知道,小编最擅长深入浅出地教大家一些知识,今天就给大家带来大神教你win ...

  8. win10添加网络打印机_大神教你设置 win10系统安装打印机及驱动的详细方案 -win10使用教程...

    人吃五谷杂粮会生病,电脑也一样.工作运行时间久了就会出现很多的问题,比如win10系统安装打印机及驱动这样的状况,大部分伙计都是第一次看到win10系统安装打印机及驱动这样的事情,想请高手帮忙解决wi ...

  9. linux 计算器 c语言,大神教你如何用C语言实现科学计算器

    原标题:大神教你如何用C语言实现科学计算器 用C实现的科学计算器 使用C语言写的科学计算器,可以实现四则运算.三角函数运算.指对数运算:优先级正确:能智能屏蔽空格,能识别输入错误和运算错误,能实现继续 ...

最新文章

  1. HDU 2955 Robberies
  2. vue 封装组件供全局使用_vue 封装组件的基本操作
  3. python输出子列表_python利用递归函数输出嵌套列表的每个元素
  4. 【linux命令】Centos下如何匹配内容在哪个文件中
  5. 数字藏品APP源码,无加密
  6. 开氏温度与摄氏度换算_政策丨车厢温度变化2……冷藏保温车国标开始征求意见...
  7. 多核支持向量机原理及实现
  8. 新加坡政府设立网络安全实验室
  9. STA之RC Corner
  10. centos7.6 安装docker
  11. linux go vendor目录,golang使用govendor教程
  12. 思科服务器首页怎么修改,修改思科服务器cimc地址
  13. 2. 样式,大纲和目录
  14. 基于FPGA的自动小车控制设计Verilog开发
  15. Arm内核的Oops错误定位方法
  16. 【ffprobe】查看TS : 视频和音频的pts、dts;查看文件的音频包/视频包总数
  17. python变量词是什么意思_Python语言基本语法元素之变量,变量的含义及命名规则...
  18. 编译器扩展-ScriptableWizard
  19. 应用在脉冲变压器中的光电耦合器
  20. 渗透武器库--burpSuite实战(最强web安全工具,没有之一)

热门文章

  1. 110道Python面试真题和面试简历资料(附链接)
  2. Python源码学习:内建类型简析并简析int对象
  3. Python设计模式-中介者模式
  4. 汇编语言的div指令 ax dx bx
  5. TCP协议的特点和TCP报文段格式
  6. 本科-人工智能模拟卷
  7. myeclipse-pro-2014-GA-offline-installer-windows 安装步骤 与安装效果预览
  8. ​别再用方括号在Python中获取字典的值,试试这个方法
  9. Android Studio编写运行测试纯java代码可带main()函数
  10. zabbix详细介绍及其自动动态发现