基于Redis有序集合的终端在线推送解决方案

本文探讨了传统终端在线状态管理方法存在的性能瓶颈,通过引入Redis有序集合,实现增量刷新机制,有效降低了磁盘IO操作,提高了系统性能。详细介绍了如何使用Redis的zadd、zcount和zrangebyscore命令来管理终端心跳信息,包括添加心跳、查询在线总量及在线状态更新流程。

问题背景

在我们的系统中,系统管理员关注所有终端的在线状态。因此,管理系统需要列出每个终端当前是否在线,最后心跳(在线)时间,以及当前系统中所有在线、离线终端数量。

这是一个常见的需求。常见的方案是,终端定时给服务端发送心跳信息(例如每隔1分钟发一次心跳信息),服务端在数据库中维护一张终端在线状态表(t_client_status),该表包含终端(mid)、最后心跳时间(last_time)等信息。当管理员需要查看终端在线状态时,后台进程查询t_client_status表给出结果。

在终端数量较少(低于10K)时,以上提到的方案是可以满足功能需求和性能需求的。然而,当终端数量较大时,由于服务端需要频繁刷新t_client_status的last_time字段,产生大量的磁盘IO操作,导致系统性能下降,影响系统的并发数,甚至可能导致数据库崩溃。

因此,我们需要考虑更加有效的方案处理终端在线状态。

解决思路

传统的解决方案中,导致磁盘IO过多的原因,在于采用了全量更新的方式。对于每次终端上报的心跳信息,都去刷新数据库。因此,我们希望能增量地去完成刷新。我们的解决方案中,主要考虑如何完成增量刷新。

最后,我们发现,Redis的有序集合可以实现增量刷新的效果。

有序集合时Redis提供的一种集合类型的数据结构。和普通集合不同的是,有序集合中不仅保存元素,同时还保存元素的分数,并按照从顺序排列。有序集合可以用在积分榜等场景中。

Redis的有序集合提供了如下命令:

  • zadd
  • zcount
  • zrangebyscore
  • zmembers

实现细节

1.添加心跳信息

zadd("heartbeats", nowtime+heartbeat_interval, mid)

2.查询在线总量

zcount("heartbeats", nowtime, "+inf")

3.增量刷新在线状态

//1. get offline clients 
offline_list = zrangebyscore("heartbeats", "-inf", nowtime)

//2. get online clients
ret = zadd("heartbeats", nowtime+heartbeat_interval, mid)
if ret == 1 then
   online_list += mid

//3. update offline_list && online_list to db
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值