1
wangyuhang 2021-03-30 12:18:04 +08:00 via Android
你现在有哪几个方案,说下
|
2
dapang1221 2021-03-30 12:22:21 +08:00 2
能保证一个上线消息必定会受到一个下线消息吗?能的话一条记录两个字段,上线时间、下线时间,用这俩一减。不能保证的话,做心跳包机制,收到消息的数量 * 心跳包间隔就是在线时间
|
3
vcfghtyjc 2021-03-30 12:29:04 +08:00
感觉问题描述的不太清楚呀。是要设计数据库,还是设计整个系统架构?
|
4
opengps 2021-03-30 12:34:37 +08:00 via Android
我也有过类似的设计,设计出来总感觉不完美,似乎关系型数据库用起来不匹配
|
5
IvanLi127 2021-03-30 12:47:54 +08:00 via Android
今日每台设备每次上下线消息存 redis 或者数据库,次日定时统计。redis 用 list 存上线时间 下线时间,list key 日期+设备编号,应该差不多了
|
6
oott123 2021-03-30 13:20:40 +08:00 via Android
首先做个数据库,redis 还是 mysql 不重要,把设备 ID 存进去,在线状态设为不在线
收到上线消息,去数据库里改成在线;下线消息同理 然后配一个 Promethues,监控项是每台设备的当前在线情况 搞完了,然后你想用什么时序数据库存想怎么查都可以 |
7
xcstream 2021-03-30 13:25:24 +08:00
定义任务 每天计算一下所有设备的在线时长
|
8
lanqing OP @dapang1221 上线下线存一条消息,我担心 10000 台*100 天*10 次上下线 = 1000W 条数据,mysql 查询会不会有点性能问题
|
11
scofieldpeng 2021-03-30 14:47:48 +08:00
要统计在线时长,首先定义怎么判定在线这个过程,如果是设备会自动上报,
你只有 1w 各设备,mysql 一张表就能解决, sn,first_report_time,last_report_time 这 3 个字段就可以完成你说的时长+统计,每个设备每天一条记录,当收到上报信息的时候,看下这张表 sn 有没有今日的记录,没有的话 insert,first_report_time,last_report_time 写入上报时间,有的话就只需要更新 last_report_time 就好了 楼上说的普罗米修斯啥的,真没必要 |
12
scofieldpeng 2021-03-30 14:49:34 +08:00
一天 1w 条记录,就算跑一年也才 365w 条记录,这点量,太小了,随便玩
|
13
Slartibartfast 2021-03-30 14:53:38 +08:00 via iPhone
你这个用 MySQL 足够了,如果太大,就按照时间或者设备 id 分库分表。
|
14
4kingRAS 2021-03-30 15:24:08 +08:00
id 一个表,device 一个表包括上线 timestamp 。下线 timestamp, 上下线的 log 一个表,记录 id,时间,动作。
统计用 log 表在 Java 里统计。 |
15
silencegg 2021-03-30 15:26:26 +08:00
CREATE TABLE `heart_beat` (
`sn` varchar(50) DEFAULT NULL COMMENT 'sn', `start_time` varchar(50) DEFAULT NULL COMMENT '心态开始时间', `end_time` datetime DEFAULT NULL COMMENT '心跳结束时间', `online_time` bigint(20) DEFAULT NULL COMMENT '在线时长', `creat_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `reason` varchar(50) DEFAULT NULL COMMENT '原因' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='心跳' |
16
silencegg 2021-03-30 15:27:40 +08:00
这个是之前我用 EMQ 监听设备上下线的表来统计设备在线时长
|
17
4kingRAS 2021-03-30 15:28:47 +08:00
原来是担心一天内上下线次数太多啊,那就做个 trigger,log 表限制为只记录当日,0 点统计时长存入一个专门统计时间的表:id ,日期,第一次上线,最后一次下线,在线时长。虽然多了一个表,但是比较灵活。
|
18
q149072205 2021-03-30 15:41:20 +08:00
还有一个问题,如果第一天上线一直没下线 ,到第二天下线你要怎么统计
|
19
Lee2019 2021-03-30 15:42:29 +08:00
用 influxdb 之类的 tsdb 呢?
甚至直接写到 prometheus 里面? {sn="xxx", active=1/0}这种? |
20
LeeReamond 2021-03-30 15:46:05 +08:00
以天为单位展示就以天为单位储存,每天登录多长时间通过业务维护,整个系统很简单
|
21
Kinnice 2021-03-30 16:09:09 +08:00
下线时记录 时长
|
22
zardly666 2021-03-30 16:10:26 +08:00
我目前做的是以某台设备某天为一条数据存储。限定到某台机器,某一天的上下线信息都只更新这一条数据。
{ "date": "2021-03-26", "online_sum": 40044000, "device_sn": "xxxxxxxxxx", "last_online_time": "2021-03-26 12:52:36", "last_status": "online", "merchant": "xxx" } |
23
ch2 2021-03-30 16:12:44 +08:00 via iPhone
用 mongo 正好,数据类型简单的话存再多也能 cache 的住无压力
|
27
zardly666 2021-03-30 17:23:23 +08:00
@lanqing 忘记说了。每天零点有一个调度任务:
①把零点时前一天最后状态仍为在线的,用零点的时间戳减去前一天最后一次上线时间的时间戳,加和进前一天这条记录的在线时长。 ②插入一条这台机器,时间为今天的新数据,以今天零点为上次在线时长戳,在线时长为 0. |
28
zardly666 2021-03-30 17:28:28 +08:00
@lanqing 这样涉及有个弊端,就是想查看今天的在线时长,从记录查不出来,需要计算。
比如机器从昨天一直开机,在今天早上零点产生了一条数据,今天零点为上次在线时长戳,在线时长为 0. 需要用当前时间戳-今天凌晨的时间戳。 |
29
redtea 2021-03-30 17:32:36 +08:00
存 MongoDB,每隔几秒向服务器发送一次消息,超过时间视为离线。
|
30
Maboroshii 2021-03-30 18:43:00 +08:00
心跳吧, 频率越高越精准 。 丢失心跳视为下线
|
31
dapang1221 2021-03-30 18:54:14 +08:00
@lanqing 才 1kw 条数据,太小看 mysql 了。。实在不行就分表,1w 台按照 id 平均分到 10~100 个表里,而且冷数据也能定期清掉或转移
|
32
securityCoding 2021-03-30 18:56:22 +08:00
往高大上的方向整就对了
|
33
joesonw 2021-03-30 19:03:07 +08:00
influxdb 每在线 5 分钟, 插一条. 随便怎么统计.
|
34
owenliang 2021-03-30 19:10:42 +08:00 via Android
spark 处理一下就好
|
35
useben 2021-03-31 09:35:46 +08:00
心跳统计
|
36
uselessVisitor 2021-03-31 09:48:11 +08:00
我们是冗余了一张最新设备信息表
|
37
LeeReamond 2021-03-31 11:38:33 +08:00 via Android
@dapang1221 1kw 慢明显是没优化,不用嘲讽楼主了。。不过话说回来 mysql 确实跟同类产品比性能不行啊,pg 和 oracle 大概 1kw 数据没优化硬顶也能顶住吧
|
39
SHSF 2021-04-03 16:39:33 +08:00
没人提 MQTT 吗
|