玖叶教程网

前端编程开发入门

到点提醒功能如何实现简单,不如试试Redis

我们经常在网上看到某个活动,如果活动还没开始 ,我们经常可以到点提醒我,那么,到点提醒这个功能,该如何实现呢?



最简单的做法,就是每次用户订阅的时候,插入一条数据到数据库里面,然后找一台机器,开启一个进程,定时地从数据库里面捞数据,捞取到数据之后再调用第三方push接口推送数据。这个设计非常简单,但是存在什么问题呢?那便是存在单点问题,如果负责读取数据的机器挂了,或者那个时间点正在发布,岂不是用户就收不到推送了?

如果我们使用多台机器,又有可能存在并发问题,例如A机器跟B机器同时读到用户甲需要发送提醒,用户就有可能同时收到两条提醒。为了避免这个问题,我们可能需要使用Redis实现一个分布式锁。那么我们有没有其他方案呢?



今天我们来分享一个使用Redis实现的延迟队列,在此之前,我们分享过Redis的基本数据结构,我们都知道,Redis有5种基本数据结构,字符串、队列、哈希、集合与有序集合。今天我们就要用有序集合,来实现一个延迟队列的功能。



我们都知道,有序集合的内部是一个跳表+哈希,跳表的一个特点是能够保证数据的有消息,所以我们就能把任务的执行时间按照从小到大的时间排序,队首的元素就是需要最早执行的任务。这里我们简单地学习几个Redis的命令,分别是添加ZADD,移除ZREM,与查询ZRANGEBYSCORE。

#ZADD 集合名 分数 关键字

当有用户点击订阅提醒我的时候,我们就把提醒的时间作为分数,把用户的id+订阅内容的id作为key,插入到我们定义的一个集合里面。如果用户取消订阅提醒,那么,我们就把对应的id删除

#ZRANGEBYSCORE 集合名 最小值 最大值

每一秒钟,我们都可以用这个去查询当前需要执行的任务有哪一些,例如当前的时间戳为1558193281,那么我们只要执行命令ZRANGEBYSCORE 集合名 0 1558193281,就能查询到在此之前有多少任务满足条件。

#ZREM 集合名 内容

当我们查询到有哪些任务需要执行的时候,我们需要将他们移除,这样子才不会被其他任务所执行。这个命令就是用来移除对应的任务。

这里,可能有同学就会想到,如果多台机器获取到同一个任务,那岂不是会冲突么?好在我们可以使用lua script帮我们把查询跟删除的命令变成再服务端的一次原子操作。只要简单的几个命令,我们就能够实现一个延迟队列。剩下的时间,我们可以用来研究怎么找对象了。

如果细心的同学机会发现,用Redis实现的延迟队列,并不能保证可用性100%,有可能会丢消息。这里的有如下这些原因:

1.redis主备之间可能存在一致性问题,如果部署redis的主机挂了可能会丢数据。

2.在机器取到任务的时候,就把任务删除了,如果这个时候死机或者发送失败,也会丢消息

如果我们要保证更高的可用性,我们可以使用延迟队列,常见的有RMQ或者卡夫卡,都有提供更高一致性,更高可用的延迟消息。每次用户订阅一个提醒的时候,往队列里面添加一个任务,并且写入对应的延迟时间。当然,越是复杂的方案,开发起来就越复杂,至于要选择复杂的方案还是简单的方案,那就要看业务的重要程度跟大家的取舍了。

今天的介绍我们就讲到这里,有没有学习到Redis新的姿势呢,后面我们再继续将Redis的一些命令与应用。如果你有兴趣,欢迎关注我,主讲算法相关的,近期还准备了一些AI相关的知识,整理后会和大家继续分享。大家的支持是我继续唠嗑的动力。(同名公众号:沙茶敏碎碎念)

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言