我在Redis数据库中有4个密钥。密钥从现在开始有效期为10秒。我已经将钥匙添加到了一套。当密钥到期时,它们实际上不再在数据库中(get返回null值)。但是,键仍然是该组的成员。该集将继续存在,直到从集合中删除密钥,此时它从数据库中消失得太有效。
当密钥到期时,是否可以自动从其所属的集合中删除密钥?
我正在考虑维护每个密钥一组以维护它所属的集合(在密钥和集合之间建立有向图集关系),然后注册密钥到期事件以在必要时删除集合成员。作为db的使用者,这是一个很大的开销,而不是作为某种后台清理线程。而且,这种方法对于清理集合来说是“尽力而为”,因为订阅到期事件的消费者代码可能会崩溃,无法获取通知,积压等等。
我可以通过将密钥集建模为哈希集中的字段来避免任何欺骗,但我希望在实践中每个密钥具有不同的到期TTL。如果可能,那怎么回事?
例如,这是我的“foo”键集。
mine:0>set foo1 barA
OK
mine:0>set foo2 barB
OK
mine:0>set foo3 barC
OK
mine:0>set foo4 barD
OK
可以将它们添加到一组中。
mine:0>sadd foo foo1 foo2 foo3 foo4
4
mine:0>smembers foo
1) foo1
2) foo3
3) foo4
4) foo2
密钥可能会过期......
mine:0>expire foo1 10
1
mine:0>expire foo2 10
1
mine:0>expire foo3 10
1
mine:0>expire foo4 10
1
mine:0>get foo1
NULL
mine:0>get foo2
NULL
mine:0>get foo3
NULL
mine:0>get foo4
NULL
mine:0>get foo5
NULL
此时键不存在,但是设置确实存在,并且它引用了键。
mine:0>smembers foo
1) foo1
2) foo3
3) foo4
4) foo2
显式删除密钥会将其从集合中删除,然后在删除所有密钥后使其不存在。
mine:0>srem foo foo1
1
mine:0>srem foo foo2
1
mine:0>srem foo foo3
1
mine:0>srem foo foo4
1
mine:0>smembers foo
[nothing returned]
答案 0 :(得分:1)
很简单!
首先,我想指出redis中的数据没有任何参考关系! foo1作为键,foo1作为集合中的元素是两个不同的东西,不同的内存地址中的不同数据,恰好存储相同的字符串“foo1”。
其次,我的方式不需要改变你的数据模型,只需要你查询你的集合的方式。查询集合中的元素时,检查密钥是否也作为redis中的单独密钥存在,逻辑如下:
ArrayList getUnexpiredElementsInSet(String setKey){
ArrayList elements = smembers(setKey);
ArrayList resultArray = new ArrayList();
for (element in elements) {
if (exists(element)==false) {
srem(setKey, element);
}else {
resultArray.add(element);
}
return resultArray;
}
通过这种方式,当您想要查询集合中的内容时,您只会获得未过期的元素,并且还会清除过期的元素。
上面只是伪java代码,向您展示基本逻辑,您需要将此逻辑包装在lua事务中。如果你不了解redis的lua功能,那就去学习吧!它很棒,让redis超级快速而强大。如果你想利用redis的真正力量,lua是不可或缺的!请参阅Redis Lua
有些人担心脚本命令的性能损失。我可以向你保证这是不必要的。根据官方文档和我在实践中所经历的,运行脚本根本没有性能损失。 从理论上讲,这在很多方面都是可以理解的: