Redis应该如何存储带时间戳的分类实时数据?
一个物联网项目,最初选用了Linux + Twisted + MySQL + Python来构建。看重的是Twisted的扩展性。但是MySQL成为性能瓶颈。
系统架构是:
大量设备每隔0.5秒以TCP长连接方式连接Twisted Socket服务器,将实时收集的数据导入数据库中,然后Web浏览器以每隔2秒的间隔从数据库中获取数据并绘图。
数据在MySQL中以二维表形式存在:
recID,devID,timestamp(UNIX), value_1, value_2, .... value_8
由于这些数据均带时间戳,所以读取时,首先要针对特定设备ID进行时间戳对比。实际上是两个需求: 检索devID,带时间排序的数值。
在单一表格中由于前段累计数据过快,所以检索时间较长,大约超过3~5秒。
弥补方式一:是定时将Expire的数据删除,但是这在InnoDB引擎中会照成长达45秒的表锁。
弥补方式二:采用PINGPONG方式在不同表间切换,但是这会造成Socket/Web两端数据同步问题,而且表锁依然存在。
有人推荐Memcached和Message Queue来解决问题。一番折腾,发现Redis可以覆盖这两种组件。
但是现在纠结应该使用哪种数据类型存储?String, Hash, List, Set, Sorted Set?
这里面关键在于key检索是需要精确的(hh:mm:ss:ms),而目前浏览器给出的时间不够精确,给出的是时间窗(hh:mm:ss~hh:mm:ss)。直接按照Key检索可能会有遗漏。即使按照通配符检索,会出现整点遗漏的问题。
String类型有Expire,适合做queue,但是如何判断devID?
key=devId:timestamp, value=value1~8?, expire=2s
此外,Redis可以有Pub/Sub模式,不知道应该如何将实时数据设计成这种模式?
python Redis node.js twisted swoole
Answers
定时将Expire的数据删除,这个时间是多久?
Sorted Set,带有排序、定期删除、比较删除,你用Sorted Set实现应该就可以了,主要是你提到timestamp不够精确,你可以自己为它添加年月日吗?
命令可以看
http://redisdoc.com/sorted_set/zadd.html
Sorted Set的结构可以这么设计
key score(日期时间索引值) value
devID timestamp的long数值
我讲一个例子出来,有一批设备,几分种就要上报一些值,那么用Sorted Set,key就是设备id,score用日期的数值形态,value就是上报的值,它支持设置数据的过期时间,还支持你给日期删除这之前的所有数据,自带排序
不过对于你的case可能有2个问题点
1.timestamp如果只是时分秒,而过期的数据是以天为单位的话,就会造成重复的score,这样数据就脏了,所以需要一个完整的日期时间
2.Sorted Set有个小缺点,就是vlaue不能重复!
还有个问题就是你确定更换redis后的硬件可以支持吗?redis可是内存数据库,不要指望它的持久化到硬盘,哪怕你重启了,它每次也会在启动时把数据load到内存里