redis – 合并在数据存储中排序?

我正在尝试为我正在进行的项目制作一个“朋友流”.我在Redis ZSETS中保存了各个用户流.就像是:

key : { stream_id : time }
user1-stream: { 1:9931112, 3:93291, 9:9181273, ...}
user2-stream: { 4:4239191, 2:92919, 7:3293021, ...}
user3-stream: { 8:3299213, 5:97313, 6:7919921, ...}
...

user4-friends: [1,2,3]

现在,为了制作user4的朋友流,我会打电话:

ZUNIONSTORE user4-friend-stream, [user1-stream, user2-stream, user3-stream]

但是,当您尝试合并总共超过1-2000个元素的ZSETS时,ZUNIONSTORE很慢.

我真的很想让Redis在ZSETS上进行合并排序,并将结果限制为几百个元素.是否有任何现成的数据存储可以满足我的需求?如果没有,是否有任何类型的框架来开发类似redis的数据存储?

我想我可以分叉Redis并添加我需要的功能,但我希望避免这种情况.

最佳答案 人们倾向于认为zs​​et只是一个跳过列表.这是错的.它是跳过列表(有序数据结构)加上非有序字典(实现为哈希表).必须定义合并操作的语义.例如,如何合并其共同项目不具有相同分数的非不相交zset?

要为ZUNIONSTORE实现合并算法,您必须获取订购的项目(使用跳过列表很容易),在构建输出时合并它们(也恰好是zset:skiplist plus dictionary).

因为在算法开始时无法猜到结果的基数,所以我认为不可能在线性时间内构建这个跳转列表字典.它最好是O(n log n).因此合并是线性的,但构建输出不是:它失败了使用合并算法的好处.

现在,如果要实现ZUNION(即直接返回结果,不将结果构建为zset),并将结果限制为给定数量的项,则合并算法是有意义的.

支持合并连接的RDBMS通常可以这样做(但由于随机I / O的成本,这通常不是非常有效).我不知道NoSQL商店支持类似功能.

要在Redis中实现它,你可以尝试一个Lua服务器端脚本,但它可能很复杂,我认为只有当zsets远大于zunion中提供的限制时它才会有效.在这种情况下,项目数量的限制将抵消运行解释的Lua代码的开销.

最后一种可能性是在Redis源代码中用C实现它,这并不困难.缺点是为您使用的Redis版本维护补丁的负担. Redis本身没有提供这样做的框架,并且定义Redis插件(与Redis源代码隔离)的想法通常被作者拒绝.

点赞