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键空间通知 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Redis开启键空间通知实现超时通知的步骤

    Redis部分设置 修改配置文件redis.conf(Windows为redis.windows.conf) 打开该配置文件(位置取决于自己的安装位置),找到Event notification部分. 将notify-keyspace-events Ex的注释打开或者添加该配置,其中E代表Keyevent,此种通知会返回key的名字,x代表超时事件. 如果notify-keyspace-events ""配置没有被注释的话要注释掉,否则不会生效. 保存后重启redis,一定要使用当前配

  • redis键空间通知使用实现

    目录 导语 实现 在业务中使用 总结 导语 最近在开发一个定时活动,而且活动是多个场次的.这个是后就需要在活动开始的时候推送信息给客户端,结束的时候也要推送一次.简单的设计方案就是将配置缓存在redis,然后每隔一秒就轮询reids,获取配置信息,然后判断是不是到活动开始或者结束的时间点,然后推送给客户端. 但是,这里会有一个问题,如果没有到活动开始或结束的时间点,这里会造成很多无用的轮询操作.这个操作不但增大了对这个key的访问量,同时也会占用cpu,降低机器性能. redis在2.8.0版本

  • Redis开启键空间通知实现超时通知的步骤详解

    Redis部分设置 修改配置文件redis.conf(Windows为redis.windows.conf) 打开该配置文件(位置取决于自己的安装位置),找到Event notification部分. 将notify-keyspace-events Ex的注释打开或者添加该配置,其中E代表Keyevent,此种通知会返回key的名字,x代表超时事件. 如果notify-keyspace-events ""配置没有被注释的话要注释掉,否则不会生效. 保存后重启redis,一定要使用当前配

  • 使用redis实现延迟通知功能(Redis过期键通知)

    Redis 过期监听场景 业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭订单 . 网上有很多使用 Redis 过期监听的 Demo redis配置 把notify-keyspace-events Ex 这一行的注释打开 项目demo工程 项目结构如下图 maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apa

  • redis内存空间效率问题的深入探究

    前言 在使用redis时,我们会遇到一个问题,数据删除后,数据量已经不大了,但是使用top命令查看,还会发现redis占用了很对内存.实际上,因为数据删除后,redis释放内存由内存分配器管理,不会立刻返回给操作系统.所以,操作系统仍然记录着给redis分配了大量的内存 这往往会伴随一个潜在的风险点:Redis 释放的内存空间可能并不是连续的,那么,这些不连续的内存空间很有可能处于一种闲置的状态.这就会导致一个问题:虽然有空闲空间,Redis 却无法用来保存数据,不仅会减少 Redis 能够实际

  • 详解Redis 键和字符串常用命令

    目录 Redis 相关知识 Redis中的数据类型 redis 键(key) Redis字符串(String) 常用命令 String的数据结构 Redis 相关知识 Redis的默认端口号为6379 默认16个数据库,类似数组下标从0开始,初始默认使用0号库.使用命令select <dbid>来切换数据库. 如: select 8.统一密码管理,所有库同样密码. dbsize查看当前数据库的key的数量.flushdb清空当前库.flushall通杀全部库. Redis是单线程+多路IO复用

  • Redis键值设计的实践

    目录 1 优雅的key结构 2 拒绝BigKey 2.1 判断BigKey 2.2 BigKey的危害 2.3 如何发现BigKey 2.4 如何删除BigKey 3 恰当的数据类型 3.1 存储对象 3.2 Hash优化 在Redis中,良好的键值设计可以达成事半功倍的效果,而不好的键值设计可能会带来Redis服务停滞,网络阻塞,CPU使用率飙升等一系列问题,今天就教大家如何设计一个良好的key-value 1 优雅的key结构 Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约

  • Redis 键值设计使用总结

    目录 前言 Redis使用中不规范的现象 Redis 使用业务场景推荐与建议 如何设计出优雅的key 一.遵循如下几个最佳实践约定 二.尽量避免bigkey 三.使用恰当的数据类型 Redis 缓存在实际应用中的使用建议 使用业务规范 前言 对redis的使用,想必做过后端开发的同学都不陌生,redis为key/value非关系型数据库,使用起来简单高效,支持的数据类型也比较丰富,几乎在日常开发中没有不涉及的: 但如果对redis使用比较深入的话,还需要综合考虑多方面的因素,比如使用redis时

  • Redis swap空间(虚拟内存)的使用详解

    swap空间对于操作系统来说比较重要,当我们使用操作系统的时候,如果系统内存不足,常常会将一部分内存数据页进行swap操作,以解决临时的内存困境.swap空间由磁盘提供,对于高并发场景下,swap空间的使用会严重降低系统性能,因为它引入了磁盘IO操作. 在Linux中,提供了free命令来查询操作系统的内存使用情况,free 命令的结果中也包含了swap相关的情况,例如下面的结果中: [root@VM-0-14-centos ~]# free -ht total used free shared

  • Java操作Redis2种方法代码详解

    Java操作Redis的方式有下面两种: 一.jedis (1)maven配置 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> (2)相关类 单节点:redis.clients.jedis.Jedis 集群:redis.clien

随机推荐