需求是这样: 有一个队列,队列中的元素是不断变化的,想知道这个队列中所有元素的和。
队列元素的增加: 当一个请求到来时,就往队列中添加元素。 可能同时到来上百个请求
队列元素的删除: 按照时间删除,当请求到来超过一定时间后,自动删除。
说白了就是想维护一个时间窗口,并查询窗口中元素之和。
我目前想过的两种做法:

利用 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

刚好我们也有这样一个物联网项目,数据量挺大,需要查固定周期内的数据来求和,感谢楼上老哥些的方法