基于Redis有序集合的终端在线推送解决方案
2015-11-28 00:13
555 查看
问题背景
在我们的系统中,系统管理员关注所有终端的在线状态。因此,管理系统需要列出每个终端当前是否在线,最后心跳(在线)时间,以及当前系统中所有在线、离线终端数量。这是一个常见的需求。常见的方案是,终端定时给服务端发送心跳信息(例如每隔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
相关文章推荐
- redis 持久化 RDB 和 AOF
- redis源码阅读-事件机制
- redis学习#随便瞎玩的收获2 -server
- Redis failover过程
- 关于Redis的ACID
- Linux操作系统安装redis
- Redis常见问题及处理方法
- 30个php操作redis常用方法代码例子
- 2.redis学习笔记:redis List底层数据实现(通用双端链表)
- Redis入门,集群安装
- redis优化配置和redis.conf说明
- Redis Java客户端实例
- Redis在Windows上编译(Visual C++2013)
- 在windows上以服务方式运行Redis服务
- redis 本机链接服务端命令
- redis实战(java项目应用)
- centos7下安装配置redis3.0.4
- NodeJs与Redis实现高并发的队列存储
- NoSQL--Redis简介
- Redis资源