使用 redis 如何维护一个动态的区间和?
需求是这样: 有一个队列,队列中的元素是不断变化的,想知道这个队列中所有元素的和。
队列元素的增加: 当一个请求到来时,就往队列中添加元素。 可能同时到来上百个请求
队列元素的删除: 按照时间删除,当请求到来超过一定时间后,自动删除。
说白了就是想维护一个时间窗口,并查询窗口中元素之和。
我目前想过的两种做法:
利用 redis 的 key 过期时间进行。 但是 key 过期的时候,无法直接反应到 sum 上。 每次请求 sum 都要把队列中的元素累加一遍,可能不太合理?
队列中存储元素的时间戳,定时(比如 100ms )来根据元素的时间戳进行逐个删除,删除的同时维护区间和。 删除到第一个在时间窗口中的元素为止。 (队列从右边加入元素,从左边删除元素)
第一次使用 redis ,想问问各位大佬这个操作要如何进行比较合理?
你是想做...访问限流?
#1 类似吧,在做一个智能算力的项目,会根据区间和的大小来动态分配算力。
google 一下“redis 限流”,解决方案很多
sored set ,zremrangeByScore ?
sored->sorted
方案 2 挺好的
#4 感谢回复,用 sorted set 的话的确可以一下子把过期的元素全部删掉,但是 sum 的维护还是要把删掉的元素列表拿出来逐个进行,是吧?
#3 感谢老哥提供的关键字,我去搜了下,看到了这个 segmentfault.com/a/1190000040570911 其中"计数器"这个方案和我想要的比较类似。 但是差别是,计数器只需要知道一个集合中元素的个数就可以了,我需要知道集合中元素之和。 这个好像要通过写 lua 脚本(?) 之类实现,听说会比较影响性能
就用方案 2 吧.
看你的量比较大. 如果流量比较稳定, 可以不需要定时器, 只在查询和插入之前清空过期数据,
不过这样也有可能某次删除了大量数据导致单次请求很慢的问题.
删除的时候可以写个 lua, 性能好点.
#9 感谢回复。 如果使用方案 2 的话,我这里用一个 list 是合理的吗? 不太了解 redis 的线程安全问题。 我这里是假定了队列中的元素是会按照时间戳严格单调排列,也就是更新的元素一定在旧的元素的右边。 这个假定是可以保证的嘛?
滑动窗口算法( Sliding Window Algorithm )
redis 本身你可以认为是单线程处理所以不用考虑线程安全问题,使用 lua 的话其实比你用命令方式访问性能还高些,相当于打包处理,放心的用吧,就你的这个需求来看,用 lua 很合适
Sorted Set 吧。
定期删除 zremrangebyscore
获取元素之和 zrangebyscore 然后自己代码里加就行了
#12 好的,感谢,我去研究研究😁
#13 感谢,我也看看这个方案
#11 感谢回复,虽然和我问的没什么关系😅
推荐一本书,应用六和应用七章节
github.com/Zhengfangxing/Book/blob/master/Redis%E6%B7%B1%E5%BA%A6%E5%8E%86%E9%99%A9%EF%BC%9A%E6%A0%B8%E5%BF%83%E5%8E%9F%E7%90%86%E5%92%8C%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5.pdf
#17 感谢老哥授人以渔,我之后读一读
#10 这个不能保证,因为时间戳是你程序生成的。 但是误差也就影响个几毫秒,对你业务没影响。
#19 好的,明白了。 那确实应该没有影响
第二种方式没问题,resilience4j 中就有与这种做法类似的做法
#21 感谢解答
如果 redis 的版本大于 5 ,建议使用 流 这种数据结构。
XADD 命令还提供了 MAXLEN 选项,让用户可以在添加新元素的同时删除旧元素,以此来限制流的长度:
XADD stream [MAXLEN len] id field value
刚好我们也有这样一个物联网项目,数据量挺大,需要查固定周期内的数据来求和,感谢楼上老哥些的方法
先说自己的需求 全家人的文件、照片备份 相册 相册的 AI 识别功能 手机同步 能方便的整合其他家人拍的照片 文件 增量备份 随用随下 互相共享 外部分享 影音 看电影…
第三方 rom 多,买一个前两年的机器,可以折腾的东西不少 别的手机第三方 rom 感觉不多,一加的多吗? 真我不准备买了 海外机器配置又低,只能在国产机器里面选了,目前看最合…
查了下拼多多,红白机现在有 HDMI 插头,但只能连智能电视,不能连普通的显示器。 普通的带屏幕的游戏机屏幕又太小(最大的也才跟手机屏幕差不多大) 模拟器 PC 上安装…
合速度