全文索引和搜索是如今应用程序的一个常见功能。用户希望能够通过在用户界面上输入一些搜索词,快速找到一家餐馆、一个产品、一篇电影评论或其他任何东西。许多这样的应用程序都是使用关系型数据库作为数据存储的,所以这些应用程序一般不是专门用于搜索的,而是将其作为一个附加功能。
对于[使用CockroachDB的开发者]来说,全文搜索选项确实还不存在于数据库本身。尽管[CockroachDB确实支持Levenshtein和Soundex],而且这些可以以新的方式结合起来,支持较短的数据元素的模糊匹配,但建立全文搜索的努力才刚刚开始。
说到这里,[CockroachDB确实支持changefeeds],或者叫Change Data Capture(CDC)。Changefeeds允许你根据DB中表的变化来配置事件流,这些事件可以被发送到消息队列(如Kafka)、S3桶,甚至是HTTP(S)端点。一旦配置好,任何INSERT、UPDATE、DELETE都会产生一个事件,可以由另一个进程来执行。这个进程甚至可以是[Elasticsearch]这样的东西,它将提供全文索引和搜索能力。
这个例子的目的是为了说明CockroachDB与Elasticsearch的整合模式,所以它被简化为只有一个表,而这个表是面向存储取自URL的数据。在现实世界中,我们可能会有多个具有外键关系的表。
解决方案技术栈概述
我选择在谷歌云平台上部署的虚拟机中运行,在us-central1地区,因为CockroachDB无服务器在该地区可用。在目前可用于[CREATE CHANGEFEED]的各种类型的终端中,没有一个能直接与Elasticsearch期望的输入相一致,所以我需要创建一个[Python Flask应用],作为CockroachDB和Elasticsearch之间的适配器。我还决定在虚拟机上直接运行Elasticsearch实例。由于加密所有这些通信似乎是一个好主意,我运行了一个[Nginx]实例,作为Flask应用和Elasticsearch的代理。[Let's Encrypt]负责处理SSL证书。我使用[Google Domains]做DNS,这样我的Let's Encrypt设置就能正常工作。最后,我把这个虚拟机作为一个 "大本营",在那里运行[HTML索引器]。
设置。基础设施
- Ubuntu 22.04 LTS运行在
e2-standard-2VM上,配有64GB SSD。 - 网络,子网是
default,其中443端口为HTTPS流量开放。 - 在虚拟机上。
sudo apt update然后sudo apt install postgresql-client - 使用默认配置启动ES,并记录下 "弹性用户的密码 "以备后用。
- 将GitHub repo的内容转移到虚拟机上(例如:
git clone https://github.com/mgoddard/crdb-cdc-elastic.git)。 - 安装了pip。
sudo apt install python3-pip - 安装了Python依赖项。
sudo pip3 install -r requirements.txt - 安装了Nginx。
sudo apt install -y nginx - 在DNS中为虚拟机设置一个 "A "记录,使用其外部IP地址(在我的例子中,它被解析为 "cdc.la-cucaracha.net")。
- 按照这个程序,为我的Nginx安装获得Let's Encrypt SSL证书。
- 用这个文件的编辑版本替换生成的
/etc/nginx/nginx.conf,然后重新启动Nginx - 通过这个用户界面在与虚拟机相同的区域设置了一个CockroachDB无服务器实例。
- 创建一个CockroachDB用户,并使用同一用户界面获取证书。我将其存储在一个文件中,
CC_cred.txt。 - 按照Serverless用户界面上的 "Download CA Cert (Required only once) "指示下载了CA证书。
- 创建了一个名为
defaultdb的Elasticsearch索引(CockroachDB数据库映射到Elasticsearch索引)。
$ export ES_PASSWD="that password recorded earlier"
$ curl -XPUT -s -k -u elastic:$ES_PASSWD https://localhost:9200/defaultdb | jq
- 启动了Flask CDC端点。
$ export ES_PASSWD="that password recorded earlier"
$ nohup ./cdc_http.py > cdc.log 2>&1
设置:蟑螂数据库
登录 CockroachDB 无服务器实例(我习惯使用 psql CLI):
$ psql $( cat ./CC_cred.txt )
psql (14.4 (Ubuntu 14.4-0ubuntu0.22.04.1), server 13.0.0)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, bits: 128, compression: off)
Type "help" for help
创建简单表以存储在 Web 上找到的文档:
defaultdb=> CREATE TABLE docs
(
uri STRING PRIMARY KEY
, content STRING NOT NULL
, ts TIMESTAMP DEFAULT NOW()
);
CREATE TABLE
启用范围源(这可能已在无服务器中设置):
defaultdb=> SET CLUSTER SETTING kv.rangefeed.enabled = true;
SET CLUSTER SETTING
将 HTTP 更改源创建到 Python Flask 端点:
defaultdb=> CREATE CHANGEFEED FOR TABLE docs
INTO 'https://cdc.la-cucaracha.net/cdc/'
WITH full_table_name, updated;
job_id
--------------------
777046877208477698
(1 row)
将 Elasticsearch 与 CockroachDB 结合使用
我正在从 VM 运行以下内容。
- 为 HTML 索引器安装额外的依赖项:
sudo pip3 install beautifulsoup4 - 为数据库连接设置环境变量:
export DB_CONN_STR=$( cat ../CC_cred.txt ) - 索引一些网址:
$ ./html_indexer.py https://www.cockroachlabs.com/blog/admission-control-in-cockroachdb/ https://www.cockroachlabs.com/blog/how-to-choose-db-index-keys/ https://www.cockroachlabs.com/docs/v21.1/example-apps.html https://www.cockroachlabs.com/docs/v22.1/multiregion-overview.html https://www.cockroachlabs.com/blog/can-i-scale/ https://www.cockroachlabs.com/blog/sigmod-2022-cockroachdb-multi-region-paper/ https://www.cockroachlabs.com/blog/living-without-atomic-clocks/ https://github.com/cockroachdb/pebble https://www.cockroachlabs.com/blog/netflix-media-infrastructure/ https://www.cockroachlabs.com/blog/full-text-indexing-search/
Indexing uri https://www.cockroachlabs.com/blog/admission-control-in-cockroachdb/ now ...
Indexing uri https://www.cockroachlabs.com/blog/how-to-choose-db-index-keys/ now ...
Indexing uri https://www.cockroachlabs.com/docs/v21.1/example-apps.html now ...
Indexing uri https://www.cockroachlabs.com/docs/v22.1/multiregion-overview.html now ...
Indexing uri https://www.cockroachlabs.com/blog/can-i-scale/ now ...
Indexing uri https://www.cockroachlabs.com/blog/sigmod-2022-cockroachdb-multi-region-paper/ now ...
Indexing uri https://www.cockroachlabs.com/blog/living-without-atomic-clocks/ now ...
Indexing uri https://github.com/cockroachdb/pebble now ...
Indexing uri https://www.cockroachlabs.com/blog/netflix-media-infrastructure/ now ...
Indexing uri https://www.cockroachlabs.com/blog/full-text-indexing-search/ now ...
Total time: 5.30757999420166 s
- 返回 SQL CLI,检查它们是否已插入:
defaultdb=> select uri, length(content), ts from docs order by 2 desc;
uri | length | ts
--------------------------------------------------------------------------------+--------+----------------------------
https://www.cockroachlabs.com/blog/admission-control-in-cockroachdb/ | 24985 | 2022-07-07 15:33:32.685422
https://www.cockroachlabs.com/docs/v22.1/multiregion-overview.html | 21300 | 2022-07-07 15:33:33.672853
https://www.cockroachlabs.com/blog/living-without-atomic-clocks/ | 20184 | 2022-07-07 15:33:35.000319
https://www.cockroachlabs.com/blog/how-to-choose-db-index-keys/ | 16958 | 2022-07-07 15:33:32.970703
https://www.cockroachlabs.com/blog/can-i-scale/ | 14654 | 2022-07-07 15:33:34.196958
https://www.cockroachlabs.com/blog/full-text-indexing-search/ | 13387 | 2022-07-07 15:33:36.789336
https://www.cockroachlabs.com/blog/netflix-media-infrastructure/ | 12859 | 2022-07-07 15:33:36.247931
https://github.com/cockroachdb/pebble | 12504 | 2022-07-07 15:33:35.708953
https://www.cockroachlabs.com/blog/sigmod-2022-cockroachdb-multi-region-paper/ | 9454 | 2022-07-07 15:33:34.70964
https://www.cockroachlabs.com/docs/v21.1/example-apps.html | 9373 | 2022-07-07 15:33:33.307314
(10 rows)
- 尝试 ES 搜索: 搜索脚本根据通过命令行参数提供给它的术语运行“短语查询”。如果有任何搜索命中,则返回的值包括有关搜索的元数据以及表中字段的值,以及最多四个突出显示的匹配片段,长度不超过 80 个字符。请随意调整脚本以满足您的需求。
$ export ES_PASSWD="ad7yMq3nrg+2bGz-QWe*"
$ ./es_search.py database region
{
"_shards": {
"failed": 0,
"skipped": 0,
"successful": 1,
"total": 1
},
"hits": {
"hits": [
{
"_id": "public-docs-https://www.cockroachlabs.com/docs/v22.1/multiregionoverview.html",
"_ignored": [
"content.keyword"
],
"_index": "defaultdb",
"_score": 1.8865218,
"highlight": {
"content": [
"<em>Database</em> <em>region</em> is a geographic region in which a database operates.",
"You must choose a <em>database</em> <em>region</em> from the list of available cluster regions.",
"To add another <em>database</em> <em>region</em>, use the ALTER DATABASE ...",
"Each <em>database</em> <em>region</em> can only belong to one super region."
]
}
}
],
"max_score": 1.8865218,
"total": {
"relation": "eq",
"value": 1
}
},
"timed_out": false,
"took": 16
}
- 删除数据库中的此行:
defaultdb=> delete from docs where uri = 'https://www.cockroachlabs.com/docs/v22.1/multiregion-overview.html';
DELETE 1
- 再次尝试该 ES 搜索:
$ ./es_search.py database region
{
"_shards": {
"failed": 0,
"skipped": 0,
"successful": 1,
"total": 1
},
"hits": {
"hits": [],
"max_score": null,
"total": {
"relation": "eq",
"value": 0
}
},
"timed_out": false,
"took": 4
}
正如预期的那样,搜索没有返回任何结果。
结论
CDC从CockroachDB到Elasticsearch的小旅程到此结束。回顾上面提到的那篇原始博客文章,我有点漫不经心地说你可以使用 CDC 来搜索 Elasticsearch,所以现在我感觉好多了。自从我在Lucene,Solr或Elasticsearch上做了很多工作以来已经有一段时间了,而且它一直在变化,所以很可能我在这里的例子是非常基本的。无论如何,我希望它能激励您在需要时探索这种类型的集成。
感谢您抽出宝贵时间阅读本文!