技术求助帖,关于 redis 大 value 存储的问题

2020-11-30 16:41:50 +08:00
 hehe12980

这是我在 V2EX 的第一个帖子

最近遇到一个业务场景,外部接口每隔 5 秒种会给我一批温度参数, 分别为每个机器上的不同温度,需要在前台动态曲线图实时显示,前台 每次 只能 看某 1 天和某一个机器的 温度参数, 历史数据曲线图 可以查询

技术上我做了分表,每一天的数据建一张表,大概 100 台左右的机器数量,每一天的数据 172 万, 单台机器的温度数据每天大概为 1.7 万

前置条件: 任何一台机器温度数据一旦生成是不会变的,我的思路能不能放缓存中,这样就不用去 100 多万条数据,拿机器编号去匹配了

但是我尝试把 1.7 万条数据 放入 redis 中,这个时候 redis 直接报了个命令超时,应该是 value 过大,导致性能下降,IO 瓶颈太大

所以 这种场景的需求究竟要怎么处理呢? 感觉 我这个需求和股票的实时曲线很像 好难啊 呜呜呜

5766 次点击
所在节点    程序员
73 条回复
lyy16384
2020-11-30 18:12:30 +08:00
@hehe12980 #13 这 1.7 万都是你的要取的数据,具体从 redis 取还是从数据库取根本没什么区别
sagaxu
2020-11-30 18:15:05 +08:00
@hehe12980 一次取 1.7 万条数据?那为何不把这 1.7 万条放一行里面呢? mysql 也有数组或者 json 吧。
hehe12980
2020-11-30 18:16:18 +08:00
@lyy16384 去 mysql 还有通过 索引检索 但是 如果 我做一个 k-v 映射 提前放入 redis 会好点把
hehe12980
2020-11-30 18:17:58 +08:00
@sagaxu 没想过 放一行的方式 感觉有点疯狂 毕竟几 M 的数据
qq316107934
2020-11-30 18:20:02 +08:00
按照时间做分表,每小时存一个 key,然后像 1 楼说的用 list/zset,取的时候根据时间范围去批量拿,这样可以避免超时。
SlipStupig
2020-11-30 18:20:31 +08:00
你这个用法不太对,redis 单个 key 是有大小限制的,这要做非常不利于检索,机器肯定是是有标识符的,用机器名称拆分作为 namesapce,然后用小时生成一个命令空间,使用 zset 作为数据存储类型,例如:Machine1:2020-11-30:00,这个 key 代表就某一机器在 2020-11-30 的 0 点~1 点之间产生的数据,要匹配机器或者时间范围的时候,可以使用 zscan 去扫描前缀,对特定温度可以用 zscore 去检索,对于 KEY 的如果只查当天缓存,可以使用 TTL 值过期,如果性能压力特别大,就需要自己实现一个 TTL 机制去销毁 key 了
optional
2020-11-30 18:30:11 +08:00
这个需求直接存数据库加索引就行,没必要 redis,redis 不适合批量取。
lyy16384
2020-11-30 18:58:04 +08:00
@hehe12980 #23 而且只有整页刷新的时候才会查全天的数据,实时更新曲线只要查增量数据,用数据库完全不会成为性能瓶颈
614457662
2020-11-30 19:46:24 +08:00
时序数据库或者 elastic search 吧,现成的轮子用着方便快捷。
dynastysea
2020-11-30 20:24:29 +08:00
@hehe12980 我晕,一堆人也是需求没搞清楚就乱出主意,没啥查询量你告诉我用 redis 干什么? redis 解决什么问题??
4771314
2020-11-30 20:28:55 +08:00
redis 不是这样用的吧 QAQ
直接时序数据库吧,场景很合适
funky
2020-11-30 20:29:07 +08:00
timescladb
ixiaohei
2020-11-30 20:30:05 +08:00
用时序数据库吧,influxdb 你值得了解一下
makdon
2020-11-30 20:40:13 +08:00
可以了解下 Apache 的 druid,这种场景很适合
rrfeng
2020-11-30 20:41:05 +08:00
你非要用 mysql 也可以,我给你造个方案,但是估计你不会想采用:

首先如上面某同学所说,这场景根本不用 Redis,因为你每次都是取全量数据,根本没有冷热之分,而且 Redis 并发支持还有问题,不如直接从 mysql 里取。

那么现在的问题就变成了怎么从 mysql 取最快:压缩。
可以一张表暂存 push 上来的 1 小时内的数据,在某小时过去 x 分钟之后,前一小时的数据可以认为已经固化了,启动个后台线程压缩存到另一张表里。

压缩算法用什么呢?抄一下 prometheus 或者相关衍生产品的压缩算法(专门针对大量 float ),大概可以做到 1-2Byte 每个数字。这样每小时只有 1MB 的数据。
kingfalse
2020-11-30 21:13:12 +08:00
字段太大的话可以先压缩一下,再放,gzip 一下,效果很明显
iyaozhen
2020-11-30 21:26:16 +08:00
我之前是历史的存 MySQL,redis 只存最近几小时的。用 unix 时间戳做 key,反正几小时多少秒是固定的,批量拿 key 就行
hehe12980
2020-11-30 21:52:35 +08:00
@dynastysea 难道 redis 只能解决,查询量大的需求,如果 我有一个查询效率不是很高的 sql (出于业务场景可能要连表查询或者数据量太大), 如果结果是固定不变的冷数据,为什么不能放缓存呢?
MineDog
2020-11-30 21:54:37 +08:00
我觉得时序数据库更符合你的要求
liuhuansir
2020-12-01 00:19:17 +08:00
opentsdb

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

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

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

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

© 2021 V2EX