blog-post

Manticore Search: 3 years after forking from Sphinx

在2017年5月,我们对Sphinxsearch 2.3.2进行了分叉,并称其为 Manticore Search 。以下是关于Manticore Search作为Sphinx分叉的简要报告,以及我们自那时以来的成就。

为什么我们要分叉Sphinx?


首先,为什么我们要进行分叉?在2016年底,Sphinxsearch的开发工作暂停了。使用Sphinx的用户和支持该项目开发的一些客户对此感到担忧,因为:

  • 错误长时间没有修复
  • 长期承诺的新特性没有推出
  • 与Sphinx团队的沟通中断

几个月后,情况没有改变,2017年6月中旬,一群积极主动且经验丰富的Sphinx用户和支持客户聚集在一起,决定尝试将产品作为名为Manticore Search的分叉来保持。我们成功地召回了大部分之前在不同公司工作的Sphinx团队,吸引了投资,并在短时间内恢复了对项目的全面工作。

我们的目标是什么?


该分叉旨在实现三个目标:

  1. 一般代码支持:错误修复,小型和大型新特性
  2. 支持Sphinx和Manticore用户
  3. 比以前更加强化的产品开发。不幸的是,到那时,Elasticsearch在许多方面已经超过了Sphinx。

这样的事情包括:

  • 无法复制
  • 没有自动ID
  • 无JSON接口
  • 无法动态创建/删除索引
  • 没有文档存储
  • 不成熟的实时索引
  • 专注于全文搜索而不是一般搜索

使得Sphinx成为一种高度专业化的解决方案,在许多情况下需要手动调整。到那时,许多用户已经迁移到了Elasticsearch。这很可惜,因为Sphinx中的基本数据结构和算法在许多情况下潜在地,并且实际上在性能上,优于Elasticsearch。而SQL在Sphinx中比在Elasticsearch中发展得要好得多,即使到现在,仍然吸引了很多人。

除了支持现有的Sphinx用户外,Manticore的全球目标是实现上述目标以及其他功能,使Manticore Search在大多数用例中成为Elasticsearch的真正替代品。

我们已经做了什么


更加活跃的开发

如果你查看 github提交统计 ,你会看到自从分叉发生(2017年中)以来,开发速度大幅增加:

img

在到2021年3月的三年半时间里,我们发布了39个新版本。在2020年,我们每两个月发布一个新版本。

复制

许多用户已经等待Sphinx的复制多年。我们在Manticore中实现的第一个大功能之一就是复制。就像Manticore中的所有功能一样,我们尽量使其尽可能易于使用。例如,要连接到集群,你只需运行类似这样的命令:

JOIN CLUSTER posts at 'neighbour-server';

这将使集群中的索引出现在当前节点上。

Manticore的复制是:

  • 同步的
  • 基于Galera库,也用于MariaDB和Percona XtraDB。

自动ID

没有 自动ID ,Sphinx / Manticore大多被认为只是另一个数据库(mysql,postgres等)的扩展,因为必须有一些东西来生成ID。我们实现了基于UUID_SHORT算法的自动ID。唯一性保证每个服务器每秒可插入1600万条记录,这在所有情况下应该足够。

mysql> create table idx(doc text);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into idx(doc) values('abc def');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx;
+---------------------+---------+
| id                  | doc     |
+---------------------+---------+
| 1514145039905718278 | abc def |
+---------------------+---------+
1 row in set (0.00 sec)

mysql> insert into idx(doc) values('def ghi');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx;
+---------------------+---------+
| id                  | doc     |
+---------------------+---------+
| 1514145039905718278 | abc def |
| 1514145039905718279 | def ghi |
+---------------------+---------+
2 rows in set (0.00 sec)

文档存储

在Sphinx 2.3.2及之前的版本中,你只能将文档原始文本保存在字符串属性中,这些属性(像所有属性一样)存储在内存中以获得最佳性能。许多用户这样做,浪费了不必要的RAM,而这又是昂贵的,并可能在大数据量上造成意外的性能问题。在Manticore中,我们 实现了 一种新的数据类型 text,它结合了全文索引和将值存储在磁盘上的延迟读取(即值在查询的最后阶段被提取)。 “存储"字段值不可过滤,不能被排序或分组。它们只是压缩存储在磁盘上,因此没有必要在mysql/hbase/postgres和其他数据库中存储它们(除非真的需要)。这被证明是一个非常有用且常用的功能。此后,Manticore现在只需要自身即可实现搜索应用。

实时索引

在Sphinx 2.3.2及之前的版本中,许多用户在使用实时索引时遇到困难,因为它常常导致崩溃和其他副作用。我们修复了大多数已知的错误和设计缺陷,并且仍在进行一些优化(主要与自动优化和读/写/合并隔离相关)。但现在可以安全地说,实时索引可以在生产中使用,这实际上也是许多用户所做的。要提到我们添加的一些功能:

  • multithreading: 在单个实时索引的多个磁盘块中并行搜索
  • OPTIMIZE 改进: 默认情况下,块的合并不是到 1,而是到服务器核心数 * 2(可以通过 cutoff 选项进行调整)。

我们正在开发自动优化功能,以便用户完全不必担心压缩问题。

charset_table = cjk, non_cjk

以前,如果您想支持英语或俄语以外的某种语言,您通常不得不维护 charset_table 中的大数组。这很不方便。我们通过将您可能需要的所有内容放入内部 charset_table 数组中,命名为 non_cjk(适用于大多数语言)和 cjk(适用于中文、韩文和日文),简化了这一点。non_cjk 数组是 charset_table 的默认数组。现在,您可以毫无问题地搜索英语、俄语和土耳其语等:

mysql> create table idx(doc text);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into idx(doc) values('abc абв öğrenim');
Query OK, 1 row affected (0.00 sec)

mysql> select * from idx where match('abc');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

mysql> select * from idx where match('абв');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

mysql> select * from idx where match('ogrenim');
+---------------------+----------------------+
| id                  | doc                  |
+---------------------+----------------------+
| 1514145039905718280 | abc абв öğrenim      |
+---------------------+----------------------+
1 row in set (0.00 sec)

官方 Docker 镜像

我们发布并维护官方 docker 镜像 用于 Manticore Search。您现在可以在任何地方快速运行 Manticore,只要有 Docker。

  ~ docker run --name manticore --rm -d manticoresearch/manticore && docker exec -it manticore mysql && docker stop manticore

525aa92aa0bcef3e6f745ddeb11fc95040858d19cde4c9118b47f0f414324a79
mysql> create table idx(f text);
mysql> desc idx;
+-------+--------+----------------+
| Field | Type   | Properties     |
+-------+--------+----------------+
| id    | bigint |                |
| f     | text   | indexed stored |
+-------+--------+----------------+

此外,manticore:dev 标签始终指向 Manticore Search 的最新开发版本。

包存储库

所有新版本和最新开发版本可以在 https://repo.manticoresearch.com/ 找到。

从那里您还可以 轻松通过 YUM 和 APT 安装 Manticore 。我们还支持 Homebrew 并维护 Windows 的构建。

NLP: 自然语言处理

在 NLP 方面,我们做了以下改进:

  • 使用 ICU 库 进行中文分词
  • 大多数语言的默认停用词开箱即用:
mysql> create table idx(doc text) stopwords='en';
Query OK, 0 rows affected (0.05 sec)

mysql> call keywords('to be or not to be that is the question', 'idx');
+------+-----------+------------+
| qpos | tokenized | normalized |
+------+-----------+------------+
| 10   | question  | question   |
+------+-----------+------------+
1 row in set (0.01 sec)
mysql> insert into idx(doc) values('Polly wants a cracker');
Query OK, 1 row affected (0.09 sec)

mysql> select highlight() from idx where match('polly cracker');
+-------------------------------------+
| highlight()                         |
+-------------------------------------+
| <b>Polly</b> wants a <b>cracker</b> |
+-------------------------------------+
1 row in set (0.10 sec)

新的多任务模式

对于多任务,Manticore 现在使用协程。除了代码变得更简单和更可靠外,不再需要为不同的索引使用不同的 dist_threads 值来使搜索并行化。现在有一个全局设置 threads,默认值等于服务器上的核心数量。在大多数情况下,您无需对其进行任何调整以获得最佳性能。

WHERE 中的 OR 支持

在 Sphinx 2/3 中,您不能轻易使用操作符 OR 按属性过滤,这是一大限制。我们在 Manticore 中修复了这一点:

mysql> select i, s from t where i = 1 or s = 'abc';
+------+------+
| i    | s    |
+------+------+
|    1 | abc  |
|    1 | def  |
|    2 | abc  |
+------+------+
3 rows in set (0.00 sec)

Sphinx 3:
mysql> select * from t where i = 1 or s = 'abc';
ERROR 1064 (42000): sphinxql: syntax error, unexpected OR, expecting $end near 'or s = 'abc''

通过 HTTP 支持 JSON 协议

SQL 很酷。我们喜欢 SQL。在 Sphinx / Manticore 中,所有关于查询语法的内容都可以通过 SQL 完成。但在某些情况下,最好的解决方案是使用 JSON 接口,就像在 Elasticsearch 中一样。SQL 适合于查询设计,而当您需要将复杂查询集成到应用程序中时,JSON 更加出色。

此外,HTTP 允许进行许多有趣的事情:使用外部 HTTP 负载均衡器和代理,这使得实现身份验证、RBAC 等变得相当简单。

更多语言的新客户端

Even easier than using the JSON over HTTP is to to use a client for a specific programming language your application is written in. 我们为 phppythonjavajavascriptelixirgo 实现了新的客户端。它们大多数基于新的 JSON 接口,其代码自动生成,从而使我们能够更快地向客户端添加新功能。

HTTPS support

Security matters. 我们已经提供了 HTTPS support 开箱即用。尽管最好还是不要将 Manticore Search 实例暴露在互联网上,因为没有内置认证,但现在在局域网中通过客户端与 Manticore Search 传输查询和结果更加安全。mysql 接口的 SSL 也得到了支持。

FEDERATED support

In addition to SphinxSE (a built-in mysql engine that allows you to integrate Sphinx/Manticore more closely with mysql) you can now use MySQL’s FEDERATED engine which is available in MySQL and MariaDB.

ProxySQL support

ProxySQL is also supported and you can use it to make quite interesting things that expand capabilities of Manticore Search.

RT mode

One of the main changes we’ve made was the imperative (i.e. via CREATE/ALTER/DROP table) way of working with Manticore. 正如您从上面的 SQL 示例中看到的,您不再需要在配置中定义索引。与其他数据库一样,您现在可以在 Manticore 中动态创建、修改和删除索引,而无需编辑配置、重启实例、删除实时索引文件等麻烦。数据模式现在与服务器设置完全分开。这是默认模式。我们称之为 RT mode

But the declarative mode (we call it Plain mode) is still supported as well. 我们不认为这是一种残余,并且不打算摆脱它。就像您可以通过 yaml 文件或特定命令与 Kubernetes 进行双向通信一样,您也可以以类似方式与 Manticore 进行通信:

  • 您可以在配置中描述所有内容,并享受轻松的配置移植和更快速的索引部署的可能性,
  • 或者您可以动态创建索引,这使得更容易将其集成到您的应用程序中

不可能并且没有计划混合使用模式。

Percolate index

The normal way of doing searches is to store documents we want to search and perform queries against them. 但是,有些情况下我们希望将查询应用于即将到来的新文档,以发出匹配信号。有些场景需要这样做。例如,监控系统不仅收集数据,还希望在不同的事件上通知用户。这可以是达到某个指标的阈值或出现在监控数据中的某个特定值。另一个类似的案例是新闻聚合。您可以通知用户任何新新闻,但用户可能只希望在某些类别或主题上收到通知。进一步说,他们可能只对某些“关键字”感兴趣。如果您使用 percolate index,这现在在 Manticore 中都是可能的。

mysql> create table t(f text, j json) type='percolate';
mysql> insert into t(query,filters) values('abc', 'j.a=1');
mysql> call pq('t', '[{"f": "abc def", "j": {"a": 1}}, {"f": "abc ghi"}, {"j": {"a": 1}}]', 1 as query);
+---------------------+-------+------+---------+
| id                  | query | tags | filters |
+---------------------+-------+------+---------+
| 8215503050178035714 | abc   |      | j.a=1   |
+---------------------+-------+------+---------+

Works faster than in Elasticsearch

New user-friendly documentation - https://manual.manticoresearch.com

For key Manticore Search functionality there are examples for most supported clients. 手册中的搜索自然使用了 Manticore Search 作为后端。还有什么:

  • 在搜索结果中智能搜索结果高亮显示
  • HTTP 示例可以直接一键复制为带参数的 curl 命令
  • 另外,我们特别注册了短域名 mnt.cr,因此您可以非常快速地找到您当前需要的信息,通过在浏览器中 CTRL-T/CMD-T 并输入例如 mnt.cr/proximitymnt.cr/quorummnt.cr/percolate

Interactive Courses - https://play.manticoresearch.com

To make it easier to get started with Manticore Search we’ve made the platform for interactive courses https://play.manticoresearch.com and of course the courses themselves, that you can take right from your browser without installing anything at all. 几秒钟后,您可以看到 Manticore Search replication works 或者如何 highlight search results

Github as a bug tracker

We use Github as a public bug/task tracker.

Sphinx 3


Sphinx 3.0.1 was released in December 2017. Until October 2018 there were three more releases and another one in July 2020 (3.3.1, the last version as of March 2021). 许多有趣的功能出现,包括二级索引和一些机器学习能力。那么问题出在哪里?为什么人们根本需要 Manticore?其中一个原因是,不幸的是,Sphinx 3 的第一次发布和最后一次发布目前都不是开源的:

  • 从某种意义上说,Sphinx 3 的代码不可用
  • 更广泛的开源 意义上。在下载页面上 说到 Sphinx 现在是根据 “延迟 FOSS” 许可提供的。这个许可究竟是什么,以及在哪里可以找到并没有披露。尚不清楚:
  • 它是否仍然是 GPLv2(即 “延迟 FOSS” 意味着延迟 GPLv2),因为代码可能基于 Sphinx 2,而 Sphinx 2 是 GPLv2(像 Manticore 一样)。那么源代码在哪里?
  • 或者它不是 GPLv2,因为二进制文件没有附带许可证,也不知道代码是否基于 Sphinx 2?GPLv2 的限制适用吗?可以随意分发 Sphinx 3 二进制文件吗,因为没有许可证文本?
  • 自 2020 年 7 月以来没有发布任何版本。存在 许多错误 ,包括重大崩溃。它们何时会被修复?

有很多问题,但没有答案。所有这一切使得重视法律方面和项目稳定性的公司和个人使用 Sphinx 3 变得非常冒险。并不是很多公司有可能投资员工的时间在这个看起来被冰冻且许可证不明确的项目上。

总的来说,现在 Sphinx 3 可以被视为针对有限范围用户与非常具体目标的专有解决方案。很遗憾,开源世界失去了 Sphinx。我们只能希望将来会有所改变。

任何基准测试?


是的!让我们测试一下由 1M+ 条来自 HackerNews 的评论和数值属性组成的 数据集

有关测试的更多信息:

  • 从数据集构建的简单索引。索引文件的大小约为 1GB
  • 一组各种查询(132 个请求),从全文搜索到过滤和分组
  • 在具有不同内存限制的裸金属服务器上运行的 Docker
  • 我们使用 SQL 通过 mysqli 客户端从 PHP 脚本发出查询
  • 在每个新查询之前,我们清除所有缓存,包括操作系统缓存并重启 Docker,然后进行 5 次尝试,最低响应时间记录在统计中。

结果:

100 MB 限制:

img

500 MB 限制:

img

1000 MB 限制:

img

Manticore Search 的未来


因此,我们已经在清晰的开源许可证 GPLv2 下开发了一个积极的产品,具有复制、自动 ID、正确工作的实时索引、JSON 接口、不错的文档、互动课程等。下一步是什么?我们的路线图是:

新的 Manticore 引擎

自 2020 年初以来,我们一直在开发一个列存储和处理库,具有默认索引(与 Clickhouse 等相对)。对于 Manticore 和 Sphinx 用户,它将解决以下问题:

  • 在大量文档和属性中快速搜索所需的大量 RAM
  • 子最优的分组性能
  • 当部分属性不能适配到 RAM 中时的子最优过滤性能

我们已经准备好了 测试版 ,以下是一些结果,比较 Manticore 列库 + Manticore Search 与 Elasticsearch 在相同数据集上的性能(不包括全文查询,即主要是分组查询):

img

仍然有很多工作要做。该库在更宽松的开源许可证 Apache 2.0 下提供,并可以用于 Manticore Search 以及其他项目(如果 Sphinx 愿意,也可以使用)。

自动优化

我们意识到手动调用 OPTIMIZE 以进行实时索引压缩是不方便的。我们正在努力解决这个问题,并希望它会包含在下一个版本中。请在 twitter 上跟随我们,以免错过。

与 Kibana 的集成

由于用户现在可以使用新的 Manticore 引擎进行更多分析,因此能够轻松地可视化它也是不错的。Grafana 很酷,但用于全文搜索可能有点棘手。Kibana 也很好,很多人都知道并使用它。我们有 Manticore Search 和 Kibana 之间集成的 alpha 版本。它尚未公开,但一旦我们完成 bug 修复并能将其视为 beta,它将会开源。

Logstash 集成

Manticore Search 已经具有 JSON 协议。我们打算改进 PUT 和 POST 方法,使其与 Elasticsearch 的 INSERT/REPLACE 查询兼容。此外,我们计划能够根据第一个插入的文档即时创建索引。所有这些将使您能够从 Logstash、Fluentd、Beats 等工具向 Manticore Search 写入数据,而不是 Elasticsearch。

自动分片

这是另一个正在进行的项目。我们已经理解我们将面临的困难,并大致知道如何解决它们。我们计划在第二季度进行。

Logstash 的替代方案

Logstash 要求用户花费大量时间从新的 自定义 日志类型开始摄取数据。如果您添加任何新行,则解析规则必须更新。在过去几个月中,我们一直在开发一个几乎可以完全解决这个问题的系统。它将允许您几乎无需协助并且通过良好的用户界面命名字段并进行最终微调来解析日志。

如果您喜欢我们所做的,请与我们保持关注:

安装Manticore Search

安装Manticore Search