使用 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
刚好我们也有这样一个物联网项目,数据量挺大,需要查固定周期内的数据来求和,感谢楼上老哥些的方法
需要用什么样的技术,如何实现,理性探讨 需要 arm 服务器吧 系统应该是定制吧 像是模拟器那种的改一下 自己 PC 搭建,可以计算一下一个月的电费是否合算。 参考资料:…
个人认为这是一个挺不错的从C语言到Linux系统开发的教程,这本是两个网上的文档。 其中 一本是《How To Think Like A Computer Scientist…
背景:PHP 在传统公司干内部 OA 一年了,现在 CTO 要求全员转 JAVA 现公司 优点:有内部转 Java 机会,公司不会倒闭 缺点:重构完容易被踢,工作压力大不加班容…