我想獲得關於兩種方法的反饋和建議,我正在考慮使用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