如何一次性获取海量设备(以 5W 为例)的最新当前状态(在线离线打开关闭)

346 天前
 unt

仅有且已有 redis+mysql+mongo 。

目前已采用两种方式:

  1. 用户刚进入页面时直接用 HMGET 。缺点:害怕 redis 存在性能瓶颈,需要专门做优化处理,比如拆分成小批量或者使用管道;
  2. 每次 iot 数据上报时,改变 mysql 的状态字段,那样每次调用业务接口,直接就能拿到状态;

请问最合理、性能开销最小的方案是什么。请教大家一些经验。

4525 次点击
所在节点    程序员
39 条回复
LsLsLsLsLs
346 天前
redis bitmap
yannxia
346 天前
最快的肯定是 IOT 数据上传的时候就通过 Redis 的 Sub/Pub 一类的机制让服务端缓存在内存里,那 5w 就立等可取(从内存里拿)缺点嘛,不一致就想办法补偿(去数据库同步啥的)
retanoj
346 天前
需求是想统计出各种状态的计数和吗?
opengps
346 天前
内存表
des
346 天前
不说说一次性获取这么多是做什么用,列表也显示不下吧
感觉像是在线/离线统计
ytmsdy
346 天前
在 iot 的固件里加入心跳请求吧,三秒或者 10 秒一次心跳。
把设备 ID 号丢到 redis 里面,设置 60 秒的过期时间,有心跳包上来了,就把值刷新一下。
需要统计有多少设备的话,直接统计一下 redis 里面有多少个 key 就可以了。
gongquanlin
346 天前
iot 上报时改变 mysql 状态很容易就把 mysql 干炸,之前因为这个吃过很多次亏了;就缓存到 redis 里,一般不存在性能瓶颈,定期根据 key 取模分批的同步到数据库里; model 封装一下,先读缓存,缓存没有再读库(这时候基本上就是掉线了)

维护好 redis 就行了
wanwaneryide
346 天前
根据对设备状态重要程度的重视程度吧,比如说比较一般般的话,设置设备 1 分钟上报一次状态,连续多久都是非正常的状态就提醒管理者啥的。如果对时效性比较重视,30s 或者 15s 或更短上报一次状态。何必每次查看的时候再去获取状态。如果每次查看都获取一次的话,假如这批设备多人多账号管理,极端的情况,几个人间隔几秒或者几十秒刷新一下页面,服务器得炸
me1onsoda
346 天前
这一看就是列数据库的长项。redis mysql mongo 都不太符合。
如果状态只有 01 的话用 redis 的位图吧
nothingistrue
346 天前
在线离线的变更,你要用连接打开、关闭事件,以及心跳事件来触发,不要依赖业务数据上报。

要是追求强一致性,那就让 IOT 服务器先自行管理在线设备集合(一般你要有下行数据需求的话,这个是必须的功能),每次查询时,基于 IOT 服务器汇报的在线设备集合,来计算待查询设备集合的在线状态。

要是不需要强一致性,那就是你的方式 2 。

至于性能开销,实际上没法直接评估,这个是随环境变更的。比如上面俩方案,第一个性能耗费在数据读方向上面,第二个性能耗费在数据写方向上面。如果平均每设备每天上下线 1000 次,则第一个方案性能好。如果设备一两年才上下线一次,则第二个方案性能好。
unt
346 天前
@yannxia #2 方法 1 就是这么搞的呀,已经实现了
unt
346 天前
@retanoj #3 不是
@des #5 不是。是 GIS 地图展示,传统做法是根据缩放等级是视口经纬度分批展示,我们不想这么做,要一次性展示全。
unt
346 天前
@nothingistrue #10 谢谢,你提供了另一种思路,通过服务器来管理,我考虑下可行性。
unt
346 天前
@2677672 #1
@me1onsoda #9 我去了解下
unt
346 天前
@ytmsdy #6 你说的这个已经实现了,问的不是这个,依然感谢🙏
retanoj
346 天前
感觉 10 楼回答了服务端记录在离线状态的问题。
对于“GIS 展示”这个事情,我咋觉得不用考虑“一次获取”,而分批获取+有过程的展示在前端效果上可能更有好一些
unt
346 天前
@retanoj #16 一般确实是这么搞的,但是我们不决定这么操作
unt
346 天前
@gongquanlin #7 单次操作确实没问题,并发操作就炸了
Mithril
346 天前
你 5W 个设备要是时钟很准,卡在同一秒上报状态的话,那就是极限状态下一秒 5W 的写操作,你那数据库分分钟就干爆了。而且你要的是“状态转换”而不是“当前状态”。
要是我的话,会做一个用来缓冲和过滤的组件,来维护这个状态,并当数据改变时再分批写入数据库。
直接做个简单的 webserver ,内存里维护一个数组。收到数据时对比一下已有数据,如果有变更就塞队列里,然后 mysql 定期从队列同步状态写回数据库。

这程序甚至都不用做持久化,每次启动的时候从数据库里读一次全局状态,或者等 30 秒后设备给你发过来就行了。

但还是同样的问题,如果你 IoT 设备时钟很准,你这 webserver 也要好好设计才行。50K 的 IOPS 写操作对于单个 server 也不是个随随便便就能搞起来的。但好在这简单的 server 你可以横向拆分,根据请求来源的设备做个路由,分到几个实例里就行了,非常容易。
kirory
346 天前
5W 也不多啊,真有性能问题直接放应用里放个 map 不就行了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1009238

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX