TairSearch是Tair全自研的全文搜索數據結構,采用和Elasticsearch相似的查詢語法。本文介紹如何在TairSearch中使用TFT.MSEARCH命令,實現索引分片查詢。
背景信息
在TairSearch數據結構中,Key為路由的最小單位。一個Key通常對應一個Schema(元數據,由mappings和settings組成),若單個Key添加了過多文檔,則會使該Key成為大Key(BigKey),嚴重時會因該Key占用的內存超過單節點的內存限制而導致內存溢出(Out Of Memory)。
當單節點架構的緩存服務的內存容量受限時,通常采用如下方法進行擴容:
將單節點架構實例變配為集群架構實例。
將大Key拆分成多個小Key,并分散到集群架構實例的各個分片中。
TairSearch根據該原理實現了大Key的內存搜索方案:預先將大Key拆分成小Key,設計負載規則將數據寫入不同的Key中,并通過TFT.MSEARCH對該類Key進行查詢。創建該類Key時,必須使該類Key具備相同的Schema配置。更多關于TairSearch的信息,請參見Search。
推薦在集群架構(代理模式)或讀寫分離架構下使用Msearch功能,結合TairProxy組件可提升大數據場景下的查詢性能。標準架構與集群架構直連模式也能使用Msearch功能,但由于其架構沒有TairProxy組件,無法發揮該功能的特點,不推薦使用。
Msearch原理
TairSearch提供的TFT.SEARCH命令支持查詢單個Key,提供的TFT.MSEARCH命令支持對Schema配置相同的多個Key進行查詢。
當客戶端發送寫請求給TairProxy后,TairProxy會根據Slot將Key寫入對應的數據分片節點中。
Msearch功能要求多個Key的Schema配置必須相同,且拆分多Key的邏輯由您進行決策,您需要了解并控制拆分Key的索引分片規則。
當客戶端發送讀請求(TFT.MSEARCH)給TairProxy后,TairProxy會將請求分發給各個對應的數據分片節點,數據分片節點會完成各個Key的查詢與首次匯總,并將結果集返回給TairProxy,此時,TairProxy會對所有結果集進行二次打分、排序、聚合并返回最終的結果集給客戶端。
Msearch分頁
由于涉及到深度搜索,可能會返回大量結果集,因此,您可以使用分頁功能分批獲取結果集。
分頁原理
TFT.MSEARCH的分頁功能不同于TFT.SEARCH提供的from和size組合,是通過指定查詢返回的文檔總數量(size)和返回各Key下一輪查詢的游標信息(keys_cursor)實現多個Key的分頁查詢。
TFT.MSEARCH的分頁實現過程如下:
在您指定了size后,TFT.MSEARCH命令會對每個Key獲取size個結果集。
Tair會對匯總結果進行二次打分、排序、聚合,最終返回size個結果集,并返回各個Key下一輪查詢的keys_cursor(您需指定
reply_with_keys_cursor
參數為true
)。說明keys_cursor默認為0,表示第一位。
在下次查詢時,可指定上述返回的keys_cursor信息,Tair將會從各Key指定的位置之后獲取size個結果集,并重復上述步驟。
分頁示例
例如設置size為10,查詢3個Key(key0
、key1
、key2
)。
Tair會對key0
、key1
、key2
分別獲取10個結果集(此時共有30個候選文檔),對匯總結果進行二次打分、排序、聚合,輸出整體排名靠前的10個結果集,返回的keys_cursor示例為{"keys_cursor":{"key0":2,"key1":5,"key2":3}}
,表示當前10個結果集的組成為:key0
的前2個、key1
的前5個和key2
的前3個。在下次查詢時指定{"keys_cursor":{"key0":2,"key1":5,"key2":3}}
,Tair將從key0
的第3位開始向后獲取10個文檔,key1
與key2
也類似。
操作樣例
本示例以模擬熱點信息搜索進行Msearch實踐介紹。
假設每天會產生100萬條熱點信息,可以設計1個Key存儲一周的熱點信息,則每個Key預計存儲700萬個文檔數。
假設模擬場景為保留2周的熱點信息,新周期的信息可以新建Key,達到過期時間則刪除Key。
每條熱點信息具有時間屬性(datetime)、作者(author)、作者ID(uid)以及信息內容(content)。
創建索引。
# 創建2個Key,每個Key以“FLOW_年月開始日_結束日”為命名規則,需確保不同Key具有相同的Schema配置。 TFT.CREATEINDEX FLOW_20230109_15 '{ "mappings":{ "properties":{ "datetime":{ "type":"long" }, "author":{ "type":"text" }, "uid":{ "type":"long" }, "content":{ "type":"text", "analyzer": "jieba" } } } }' TFT.CREATEINDEX FLOW_20230116_23 '{ "mappings":{ "properties":{ "datetime":{ "type":"long" }, "author":{ "type":"text" }, "uid":{ "type":"long" }, "content":{ "type":"text", "analyzer": "jieba" } } } }'
添加文檔數據。
# 此處分別向每周的Key寫入一條數據為例。 TFT.ADDDOC FLOW_20230109_15 '{ "datetime":20230109001209340, "author":"熱點影視", "uid":7884455, "content":"電影在大年初一就要與觀眾見面了" }' TFT.ADDDOC FLOW_20230116_23 '{ "datetime":20230118011304250, "author":"熱點時尚", "uid":100093, "content":"推出品牌2023兔年生肖系列新品" }'
查詢示例。
搜索2周以來“生肖兔”相關的熱點信息,結果集按時間排序。
TFT.MSEARCH 2 FLOW_20230109_15 FLOW_20230116_23 '{ "query":{ "match":{ "content":"生肖兔" } }, "sort" : [ { "datetime": { "order" : "desc" } } ], "size":10, "reply_with_keys_cursor":true, "keys_cursor":{ "FLOW_2023010916":0, "FLOW_202301623":0 } }'
預計輸出:
{ "hits":{ "hits":[ { "_id":"20230118011304250", "_index":"FLOW_20230116_23", "_score":1, "_source":{ "datetime":20230118011304250, "author":"熱點時尚", "uid":100093, "content":"推出品牌2023兔年生肖系列新品" } } ], "max_score":1, "total":{ "relation":"eq", "value":1 } }, "aux_info":{ "index_crc64":14159192555612760957, "keys_cursor":{ "FLOW_20230109_15":0, "FLOW_20230116_23":1 } } }