搜索功能的技术方案(二)

0X00 弃用canal

上一回说到,我在调研搜索功能的实现方案上选用了canal组件。然而,经过实际使用,发现存在比较大的问题

  1. 不支持全量同步
  2. 搭建起来比较复杂
  3. 长期不维护

这种同步数据的中间件叫做CDC。CDC是Change Data Capture(变更数据获取)的简称。核心思想是,监测并捕获数据库的变动(包括数据或数据表的插入、更新以及删除等),将这些变更按发生的顺序完整记录下来,写入到消息中间件中以供其他服务进行订阅及消费。
于是在众多的CDC中选用组件肯定是没错的,于是我选用了著名的Apache Flink。顺带一提,我在小米时,内部大量使用了Flink,这也是促使我选用它的主要原因。

也许是在小米时培养的容器化思想,我也想将Flink-CDC进行容器化,以便于将它快速启动,快速迁移,而且解除它与ES和项目代码的耦合,也即它只做一件事——同步MySQL的数据到ES中。

0x0201

下载Apache Flink:https://flink.apache.org/downloads/
这里我使用的是V1.16.1:https://www.apache.org/dyn/closer.lua/flink/flink-1.16.1/flink-1.16.1-bin-scala_2.12.tgz
image
解压后在其中的lib目录增加flink-sql-connector-elasticsearch7-1.16.0.jar和flink-sql-connector-mysql-cdc-2.3.0.jar
下载地址为:
https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/2.3.0/flink-sql-connector-mysql-cdc-2.3.0.jar
https://repo.maven.apache.org/maven2/org/apache/flink/flink-sql-connector-elasticsearch7/1.16.0/flink-sql-connector-elasticsearch7-1.16.0.jar
配置flink参考链接:https://ververica.github.io/flink-cdc-connectors/master/content/quickstart/mysql-postgres-tutorial.html

0x0203 制作Dockerfile

通过上述的镜像,制作Dockerfile

FROM registry.cn-hangzhou.aliyuncs.com/xxxx/base-common:flink-1.6.1
ENV JAVA_HOME /jdk1.8.0_371
ENV PATH $JAVA_HOME/bin:$PATH
WORKDIR /flink-1.16.1/bin
EXPOSE 8081
CMD ./start-cluster.sh && ./sql-client.sh -i init.sql -f job.sql && tail -f /dev/null

其中,init.sql的内容为:

SET execution.checkpointing.interval = 3s;

job.sql的内容为:

CREATE TABLE competition (
id INT,
title STRING,
status STRING,
content STRING,
coverUrl STRING,
startTime TIMESTAMP(0),
endTime TIMESTAMP(0),
PRIMARY KEY (id) NOT ENFORCED
   ) WITH (
'connector' = 'mysql-cdc',
'hostname' = 'xxx.xxx.xxx',
'port' = '3306',
'server-time-zone' = 'Asia/Shanghai',
'username' = 'my_mysql_username',
'password' = 'my_mysql_password',
'database-name' = 'ideameeting',
'table-name' = 'competition'
   );

CREATE TABLE idm_competition (
     id INT,
     title STRING,
     status STRING,
     content STRING,
     coverUrl STRING,
     startTime TIMESTAMP(0),
     endTime TIMESTAMP(0),
    PRIMARY KEY (id) NOT ENFORCED
  ) WITH (
      'connector' = 'elasticsearch-7',
      'hosts' = 'http://172.22.48.1:9200',
      'index' = 'my_index',
      'username' = 'my_es_username',
      'password' = 'my_es_password'
  );
insert into idm_competition select c.id, c.title, c.status, c.content, c.coverUrl,  c.startTime, c.endTime from competition as c;

使用以下命令编译成最终镜像
docker build -t flink-v1.16.1:v1 .
得到的这个镜像就可以随时启动,并且启动后开始同步MySQL的数据到ES中

0x03 给es添加用户名和密码

docker run -it -d -p 9200:9200 9300:9300 -e "discovery.type=single-node" elasticsearch:v7.16.1

进入容器后,修改config/elasticsearch.yml的内容,添加:

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

然后执行./bin/elasticsearch-setup-passwords interaactive 设置密码

0x04 安装ik分词器

在准备就绪后,搜索时发现新的问题:搜索中文时,只支持搜索单个字符,不支持搜索词语。
这显然是分词器的问题,于是配置ik分词器
进入容器执行

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.16.1/elasticsearch-analysis-ik-7.16.1.zip

接下来,需要给索引需要搜索的字段添加mapping(无法给已存在的索引字段添加ik分词,因此需要删除原来的索引)
删除后,就可以添加配置ik分词了:

PUT http://xx.xx.xx.xx:9200/idm_competition
Content-Type: application/json

{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

然后启动flink的镜像,数据就会同步到ES中了,并且title和content字段都会开启ik分词

posted @ 2023-05-25 01:32  ABKing  阅读(33)  评论(0编辑  收藏  举报