我想获得关于两种方法的反馈和建议,我正在考虑使用Redis排序集来实现可搜索索引。使用Redis排序集索引
形势和客观
目前,我们有我们在卡桑德拉存储一些键值表,我们希望有索引。例如,一个表将包含人员的记录,而Cassandra表将以id作为其主键,并将序列化对象作为值。该对象应具有诸如first_name,last_name,last_updated等字段。
我们想要的是能够进行搜索,如“last_name ='Smith'AND first_name>'Joel'”,“last_name <'Aaronson'”,“last_name ='Smith'AND first_name ='Winston' “ 等等。搜索应该产生匹配的ID,以便我们可以从Cassandra中检索对象。我在想上面的搜索可以用单个索引来完成,按last_name,first_name和last_updated按字典顺序排序。如果我们需要使用不同顺序进行搜索(例如“first_name ='Zeus'”),我们可以使用类似的索引来允许这些索引(例如first_name,last_updated)。
我们正在研究如何使用Redis,因为我们需要能够每分钟处理大量的写入操作。我读了一些常见的方式Redis的排序是用来套,并拿出了两种可能的实现:
选项1:每个指数
对于由姓氏,FIRST_NAME我们的索引单个有序集合, last_updated,我们将在Redis下的关键索引下有一个有序集:people:last_name:first_name:last_updated,它将包含格式为last_name:first_name:last_updated:id的字符串。例如:
史密斯:乔尔:1372761839.444:0azbjZRHTQ6U8enBw6BJBw
(作为隔离我可能会使用“::”,而不是“:”或别的东西与词典顺序更好的工作,但我们忽略了现在)
这些项目都将被赋予0分,以便排序后的集合将按照字符串本身按字典顺序排序。如果我然后想要做一个像“last_name ='smith'AND first_name <'bob'”的查询,我需要获得列表中所有在'smith:bob'之前的项目。
据我所知,有以下缺点这种方法:
- 没有Redis的功能选择基于字符串值的范围。此功能称为ZRANGEBYLEX,由Salvatore Sanfilippo在https://github.com/antirez/redis/issues/324提出,但未实现,所以我将不得不使用二进制搜索找到端点并自己获取范围(可能使用Lua,或者在应用程序级别使用Python是我们用来访问Redis的语言)。
- 如果我们想要包含索引条目的生存时间,似乎最简单的方法是定期执行一项计划任务,该任务会遍历整个索引并删除过期的项目。
选项2:小的有序集合,由LAST_UPDATED
排序此方法将是类似的,除了我们将有许多,更小的,排序集合,每个具有如LAST_UPDATED一个时间样值为分数。例如,对于相同的last_name,first_name,last_updated索引,我们将为每个last_name,first_name组合有一个有序集。例如,关键字可能是索引:people:last_name = smith:first_name = joel,并且它对每个我们称为Joel Smith的人都有条目。每个条目的名称都是id,其分数是last_updated的值。例如:
value:0azbjZRHTQ6U8enBw6BJBw;得分:1372761839.444
这样做的主要优点是(a)搜索我们知道除last_updated之外的所有字段将非常容易,并且(b)使用ZREMRANGEBYSCORE可以非常容易地实现生存时间。
的缺点,这似乎是非常大的,在我看来:
- 似乎那里多了很多管理和搜索这样的复杂性。例如,我们需要索引来跟踪其所有键(例如,我们希望在某个时候清理),并以分层方式执行此操作。搜索“last_name <'smith'”需要首先查看所有姓氏的列表以找到史密斯之前出现的那些姓氏,然后对于每个查看它所包含的所有姓氏的人,然后对于每个人从其排序的集合中获取所有项目。换句话说,需要构建和担心的很多组件。
结束语
所以在我看来,第一种选择会更好,尽管它的缺点。我非常感谢任何有关这两种或其他可能解决方案的反馈(即使他们是我们应该使用Redis以外的其他解决方案)。
的[关于如何不被垃圾邮件发送者的帮助(http://stackoverflow.com/help/promotion)显然,“你必须在你的答案透露你联系。”我相应地编辑了你的答案。 – Louis