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 } } }