本文介绍TairSearch、RediSearch数据写入和搜索性能的测试方法及测试结果。

TairSearch是Tair全自研的全文搜索数据结构,采用与Elasticsearch相似的查询语法,可实现高效的全文搜索,更多信息请参见TairSearch

测试说明

客户端测试环境

测试环境信息说明
部署压测工具的设备云服务器ECS实例,规格为ecs.g7.8xlarge,详情请参见实例规格族
地域和可用区华东1(杭州),可用区K。
操作系统CentOS 7.9 64位。

数据库测试环境

在同一台ECS实例上搭建Tair数据库和Redis数据库,实例信息如下。

表 1. 自建Tair数据库
测试环境信息说明
Tair版本内存型(兼容Redis 5.0),5.0.30。
IO Thread数4
CPUTair实例绑定6个CPU,命令示例:taskset -c 1-6 ./src/redis-server redis.conf
表 2. 自建Redis数据库
测试环境信息说明
Redis版本7.0.10。
RediSearch版本2.6.6,开启CONCURRENT_WRITE_MODE
RedisJson版本2.4.6。
IO Thread数4
CPURedis实例绑定6个CPU,命令示例:taskset -c 1-6 ./src/redis-server redis.conf

测试数据

本次测试数据为维基百科公开的中文文章摘要英文文章摘要

中、英文测试数据示例如下:
{
    "id":"History_of_Pakistan",
    "title":"History of Pakistan",
    "url":"https://en.wikipedia.org/wiki/History_of_Pakistan",
    "abstract":"The history of Pakistan for the period preceding the country's independence in 1947Pakistan was created as the Dominion of Pakistan on 14 August 1947 after the end of British rule in, and partition of British India. is shared with that of Afghanistan, India."
}
{
    "id":"Wikipedia:哲学",
    "title":"Wikipedia:哲学",
    "url":"https://zh.wikipedia.org/wiki/%E5%93%B2%E5%AD%A6",
    "abstract":"哲学()是研究普遍的、基本问题的学科,包括存在、知识、价值、理智、心灵、语言等领域。哲学与其他学科不同之处在於哲学有独特之思考方式,例如批判的方式、通常是系统化的方法,并以理性论证为基础。"
}

压测工具

根据实际情况下载对应操作系统的二进制可执行文件(TairSearchBench.DarwinTairSearchBench.LinuxTairSearchBench.Windows)。

以Linux为例,执行./TairSearchBench.Linux --help可查看压测工具的使用方法,用法如下:
Usage of ./TairSearchBench.linux:
  -a string
        The address(ip:port) of network to connect 
        # 实例连接地址。
  -c int
        Benchmark concurrency (default 30)
        # 并发数,默认为30。
  -d uint
        Specify the number of seconds for the benchmark (default 30)
        # 指定测试时间,到达时间后,测试终止,默认为30s。
  -e string
        The engine backend to run [tairsearch/redisearch]
        # 指定运行引擎为TairSearch或RediSearch。
  -f string
        Input file to ingest data from (wikipedia abstracts)
        # 执行数据文件路径。
  -h string
        Print usage (default "help")
        # 显示使用方法。
  -j string
        Specify the big json file to write
        # 指定要写入的Json文件路径。
  -n uint
        Specify the number of times to benchmark (default 100000)
        # 指定总测试数,默认为100000。
  -o int
        Overwrite the doc (We will write the document with the same document id)
        # 是否覆盖写,取值为1(开启)或0(关闭,默认值)。
  -p string
        The password of redis to connect
        # 实例的密码。
  -q string
        Search query string to benchmark
        # 指定压测的查询语句。
  -s uint
        Specify the compress threshold for tairsearch (default 10000000000)
        # 指定TairSearch的文档压缩阈值,文档超过该大小会进行压缩,单位为字节,默认为10000000000(10 kb)。
  -t string
        Specify the type of benchmark [write/search/readwrite]
        # 指定测试类型为write、search或readwrite。
  -z string
        Specify the analyzer to use for query (default "standard")
        # 指定查询的分词器,默认为standard。

测试时,提前分配20个CPU进行测试,命令示例:taskset -c 10-30 ./TairSearchBench.linux

准备工作

创建Schema(索引),示例如下。
  • TairSearch:
    {
        "settings": {
            "compress_doc": {
                "size": "用户传入的压缩阈值",
                "enable": true
            }
        },
        "mappings": {
            "properties": {
                "id":       {"type": "keyword"},
                "url":      {"type": "keyword", "index": false},
                "title":    {"type": "text", "analyzer": "用户传入的analyzer"},
                "abstract": {"type": "text", "analyzer": "用户传入的analyzer"},
                "url_len":  {"type": "integer"},
                "abstract_len":  {"type": "integer"},
                "title_len":  {"type": "integer"}
            }
        }
    }
  • RediSearch:
    \\ SCHEMA
    $.id AS id TEXT
    $.url AS url TEXT NOINDEX
    $.title AS title TEXT
    $.abstract AS abstract TEXT
    $.abstract_len AS abstract_len NUMERIC
    $.url_len AS url_len NUMERIC
    $.title_len AS title_len NUMERIC
    
    \\ 如果是中文文档,需要加上"LANGUAGE CHINESE"。

测试命令与测试结果

本次除混合读写以外的各项测试均为测试100万次,例如写入100万个英文文档、基于100万个文档查询100万次等。混合读写测试为测试60s。

写入英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e tairsearch -f ./enwiki-latest-abstract.xml -c 20 -n 1000000 -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e redisearch -f ./enwiki-latest-abstract.xml -c 20 -n 1000000 -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)最终内存占用(GB)
TairSearch22615.150.8741.7351.39
RediSearch18295.101.0922.3521.67

写入中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e tairsearch -f ./zhwiki-latest-abstract.xml -c 20 -n 1000000 -a 127.0.0.1:6379 -z jieba
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e redisearch -f ./zhwiki-latest-abstract.xml -c 20 -n 1000000 -a 127.0.0.1:6379 -z chinese
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)最终内存占用(GB)
TairSearch13980.411.4273.2751.87
RediSearch10924.401.8303.8571.83
说明 TairSearch占用更多内存的原因可能是:使用了Jieba分词器,分出更细致、更多的词元(Token)。

覆盖写入英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e tairsearch -f ./enwiki-latest-abstract.xml -c 20 -n 1000000 -o 1 -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e redisearch -f ./enwiki-latest-abstract.xml -c 20 -n 1000000 -o 1 -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)最终内存占用(GB)
TairSearch9775.032.0413.9740.0002
RediSearch22239.670.8981.380.165
说明 TairSearch在覆盖写时是同步删除,而RediSearch是标记删除,标记删除可能会造成内存存在垃圾(内存浪费)。

覆盖写入中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e tairsearch -f ./zhwiki-latest-abstract.xml -c 20 -n 1000000 -o 1 -a 127.0.0.1:6379 -z jieba
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t write -e redisearch -f ./zhwiki-latest-abstract.xml -c 20 -n 1000000 -o 1 -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)最终内存占用(GB)
TairSearch6194.153.2066.4560.025(含Jieba分词器词库)
RediSearch25096.180.7961.3380.671
说明 TairSearch在覆盖写时是同步删除,而RediSearch是标记删除,标记删除可能会造成内存存在垃圾(内存浪费)。

Term查询英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"term":{"abstract":"hello"}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:hello" -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch45501.130.4370.563
RediSearch28513.870.7000.833

Term查询中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"term":{"abstract":"你好"}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:你好" -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch40670.470.4890.635
RediSearch24437.480.8171.331

Match查询英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"match":{"abstract":{"operator":"and","query":"chinese history"}}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:chinese history" -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch24548.940.8120.971
RediSearch2420.668.2618.523

Match查询中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 100000 -q '{"query":{"match":{"abstract":{"operator":"and","query":"中国的历史"}}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 100000 -q "@abstract:中国的历史" -a 127.0.0.1:6379  -analyzer jieba
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch6601.053.0273.669
RediSearch889.3722.48622.985

Bool查询英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 100000 -q '{"query":{"bool":{"must":[{"term":{"abstract":"war"}},{"term":{"abstract":"japanese"}},{"range":{"abstract_len":{"gt":500}}}],"must_not":{"term":{"abstract":"America"}},"should":[{"term":{"abstract":"chinese"}},{"term":{"abstract":"china"}}]}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 100000 -q "@abstract:(war japanese -America (chinese|china)) @abstract_len:[500 +inf]"  -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch4554.224.3885.702
RediSearch1124.0817.79118.444

Bool查询中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 100000 -q '{"query":{"bool":{"must":[{"term":{"abstract":"战争"}},{"term":{"abstract":"日本"}},{"range":{"abstract_len":{"gt":500}}}],"must_not":{"term":{"abstract":"美国"}},"should":[{"term":{"abstract":"中国"}},{"term":{"abstract":"亚洲"}}]}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:(战争 日本 -美国 (中国|亚洲)) @abstract_len:[500 +inf]"  -a 127.0.0.1:6379 -analyzer jieba
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch2619.007.62318.42
RediSearch1199.7616.66917.064

Range查询英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"range":{"abstract_len":{"lte":420, "gte":400}}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract_len:[400,420]" -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch2840.027.0388.599
RediSearch1307.0215.30016.817

Prefix查询英文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"prefix":{"abstract":"happiness"}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:happiness*" -a 127.0.0.1:6379
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch36491.100.5450.688
RediSearch25558.920.7810.930

Prefix查询中文数据

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e tairsearch -c 20 -n 1000000 -q '{"query":{"prefix":{"abstract":"开心"}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t search -e redisearch -c 20 -n 1000000 -q "@abstract:开心*" -a 127.0.0.1:6379 -z chinese
测试结果:
对比项QPS(次/秒)Average Latency(毫秒)99th Percentile Latency(毫秒)
TairSearch41308.710.4810.638
RediSearch27457.860.7271.234

混合读写测试(Write与Term查询)

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t readwrite -e tairsearch -f ./enwiki-latest-abstract.xml -c 20 -d 60 -q '{"query":{"term":{"abstract":"hello"}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t readwrite -e redisearch -f ./enwiki-latest-abstract.xml -c 20 -d 60 -q "@abstract:hello" -a 127.0.0.1:6379
测试结果:
对比项平均写入QPS(次/秒)平均写入Average Latency(毫秒)平均查询QPS(次/秒)平均查询Average Latency(毫秒)
TairSearch14699.77 1.35916224.031.232
RediSearch11386.751.75511386.701.755

混合读写测试(Write与Bool查询)

测试命令:
  • TairSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t readwrite -e tairsearch -f ./enwiki-latest-abstract.xml -c 20 -d 60 -q '{"query":{"bool":{"must":[{"term":{"abstract":"war"}},{"term":{"abstract":"japanese"}},{"range":{"abstract_len":{"gt":500}}}],"must_not":{"term":{"abstract":"America"}},"should":[{"term":{"abstract":"chinese"}},{"term":{"abstract":"china"}}]}}}' -a 127.0.0.1:6379
  • RediSearch:
    taskset -c 10-30 ./TairSearchBench.linux -t readwrite -e redisearch -f ./enwiki-latest-abstract.xml -c 20 -d 60 -q "@abstract:(war japanese -America (chinese|china)) @abstract_len:[500 +inf]" -a 127.0.0.1:6379
测试结果:
对比项平均写入QPS(次/秒)平均写入Average Latency(毫秒)平均查询QPS(次/秒)平均查询Average Latency(毫秒)
TairSearch9589.18 2.08510504.311.903
RediSearch5284.013.7845283.963.784

总结

TairSearch通过内部精巧的倒排索引设计,充分利用多核并行计算的能力,实现了高吞吐、低延时的读写性能。同时,在保证不显著降低读写性能的前提下,TairSearch尽可能地使用压缩型数据结构,以降低内存消耗进而降低使用成本。