elasticsearch集群与搜索

elasticsearch简介

ES是基于Lucene的搜索服务器。它提供了一个分布式多用户的全文搜索引擎,基于RESTful web接口。ES是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎;

Sphinx和ES比较:

  1. 在复杂查询逻辑下,Sphinx使用非常麻烦,在特定情况下,还需修改Sphinx源码才能实现需求,而ES天生就拥有非常丰富的Query DSL,可以满足几乎任何的检索情况;
  2. 另一方面,在横向扩展和高可用方面,Sphinx实现分布式可谓是没事找抽型,它并不是做不到,而是实在是太难用了,而ES从一出生就是为分布式、集群化而生的,不仅方便横向扩展、动态增加节点。

solr与ES比较:

  1. 当单纯对已有数据进行搜索时,Solr更快。当实时建立索引时, Solr会产生io阻塞,查询性能较差, ES具有明显的优势。随着数据量增加,Solr搜索效率会变得更低,而ES却没有明显的变化;
  2. solr要借助tomcat实现http请求,而ES无需额外搭建tomcat;
  3. Solr 利用 Zookeeper 进行分布式管理,而 ES 自身带有分布式协调管理功能;
  4. Solr 支持更多格式的数据,而 ES 仅支持json文件格式;
  5. Solr 在传统搜索应用中表现好于 ES,但在处理实时搜索应用时效率明显低于 ES

构建elasticsearch集群

引入的docker镜像
docker pull elasticsearch:7.6.1
docker pull kibana:7.6.1
本次采用1主2从的集群配置,使用docker构建elasticsearch容器运行,安装ik中文分词插件,搭配kibana可视化工具管理
/mnt/hgfs/elasticsearch/master_10/config/elasticsearch.yml配置

cluster.name: elasticsearch-cluster
node.name: es-master-10
network.host: 0.0.0.0
network.publish_host: 180.200.7.10
http.port: 9200
transport.tcp.port: 9300
http.cors.enabled: true
http.cors.allow-origin: "*"
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["180.200.7.10:9300","180.200.7.11:9300","180.200.7.12:9300"]
discovery.zen.minimum_master_nodes: 1
cluster.initial_master_nodes: es-master-10

/mnt/hgfs/elasticsearch/slave_11/config/elasticsearch.yml配置

cluster.name: elasticsearch-cluster
node.name: es-node-11
network.host: 0.0.0.0
network.publish_host: 180.200.7.11
http.port: 9200
transport.tcp.port: 9300
http.cors.enabled: true
http.cors.allow-origin: "*"
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["180.200.7.10:9300","180.200.7.11:9300","180.200.7.12:9300"]
discovery.zen.minimum_master_nodes: 1

对应的docker-compose.yml
docker-compose.txt

安装ik插件

在宿主机创建插件目录,下载对应版本的ik插件文件放入解压,然后共享插件目录给每个es容器

mkdir /mnt/hgfs/elasticsearch/plugins/ik
cd /mnt/hgfs/elasticsearch/plugins/ik
upzip elasticsearch-analysis-ik-7.6.1.zip
rm elasticsearch-analysis-ik-7.6.1.zip

运行启动es容器
docker-compose up -d
QQ截图20220814180454.png

构建集群注意事项

  1. 每个es容器在构建的时候是需要系统提供200M的内存(建议实现)
  2. 宿主机系统需要配置 sysctl -w vm.max_map_count=262144 参考地址https://www.jianshu.com/p/79946b7a9c48
  3. 配置es的共享目录的时候需要给文件操作的权限777
    chmod -R 777 /mnt/hgfs/elasticsearch/

管理查看elasticsearch

1.浏览器管理http://192.168.3.66:5601/app/kibana#/dev_tools/console
2.下载elasticsearch-head组件管理,直接打开index.html

PHP使用elasticsearch

在网站根目录运行安装对应版本的elasticsearch组件
composer require elasticsearch/elasticsearch 7.6.1
创建es文件夹,添加Elastic.php操作类,执行es.php测试
es.rar
创建一个文档索引archive

$params = [
    'index' => 'archive',
    'body' => [
        'settings' => [
            'number_of_shards' => 3,    //分片
            'number_of_replicas' => 1   //副本集
        ],
        'mappings' => [
            '_source' => [
                'enabled' => true
            ],
            'properties' => [
                'title' => [
                    'type' => 'text',
                    //ik分词器
                    "analyzer" => "ik_max_word",
                    "search_analyzer" => "ik_max_word"
                ],
                'content' => [
                    'type' => 'text'
                ],
                'aid' => [
                    //数值
                    'type' => 'integer'
                ],
            ]
        ]
    ]
];
Elastic::createIndex($params);

查看elasticsearch-head

elasticsearch结构

QQ截图20220814201724.png
如图所示,上图细框长方形为副本分片,粗框长方形为data分片,五角星代表master节点
1.分片结构:这个索引一共有6个分片,3个shard分片集,每个shard有1个data数据集,1个replica副本集,es是基于Lucene内核的,6个分片,就是6个Lucene内核。
2.分片分布: 3个shard会自动分布在3台服务器上,大家可以看到,每台服务器上分布的分片数量是一样多,这个均衡分布是es内部机制完成的,shard对应的replica是不会在同一台机器上面的。
3.主从节点: 如上图,es-master-10为master节点,es-node-11和es-node-12为从节点。我们的主节点,负责管理:集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。但是,主节点并不处理文档级别的增删改查。
不论我们有多少个es实例,当用户需要对es进行增删改查的时候,连接任何一台节点都行,es内部会进行自动进行路由转发。这也是es集群的个性之一。

elasticsearch故障转移与扩容

docker stop es_master_180_10
docker ps -a
QQ截图20220814204823.png
当主节点出现故障时,集群会自动选举一个从节点成为主节点,并自动重新进行分片操作。

ES与mysql结构类比

MySQL中的数据库(DataBase),等价于 ES 中的索引(Index)。
MySQL中数据库下面有 N 张表(Table),等价于索引 Index 下面有 N 多类型(Type),ES7+版本则只有一个类型Type=_doc。
MySQL 中一个数据库表(Table)下的数据由多行(Row)多列(column,属性)组成,等价于1个 Type 由多个文档(Document)和多 Field 组成。
MySQL 中定义表结构、设定字段类型等价于 ES 中的 Mapping。举例说明,在一个关系型数据库里面,Schema 定义了表、每个表的字段,还有表和字段之间的关系。与之对应的,在 ES 中,Mapping 定义索引下的 Type 的字段处理规则,即索引如何建立、索引类型、是否保存原始索引 JSON 文档、是否压缩原始 JSON 文档、是否需要分词处理、如何进行分词处理等。
MySQL 中的增 insert、删 delete、改 update、查 search 操作等价于 ES 中的增 PUT/POST、删 Delete、改 _update、查 GET。其中的修改指定条件的更新 update 等价于 ES 中的 update_by_query,指定条件的删除等价于 ES 中的 delete_by_query。
创建一个索引相当于创建一个库,索引一个文档相当于给库的某个表中新增一条记录,获取/搜索一个文档相当于获取某一个库的某个表中的一条记录,删除一个文档相当于删除这条记录,删除一个索引相当于删除了这个库。

elasticsearch搜索

查询介绍:
must 返回的文档必须满足must子句的条件,并且参与计算分值;
filter 返回的文档必须满足filter子句的条件,但是不会像must一样,参与计算分值;
should 返回的文档可能满足should子句的条件.在一个bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回;
must 和 should 并列条件组合时,参数 minimum_should_match 默认为0 (即 should 的条件可以都不满足)。这也是 must 和 should 组合查询时,should 失效的原因。
should下有多个条件时,必须设置参数 minimum_should_match 为1 才能实现 或 操作。
must_not 返回的文档必须不满足定义的条件
matchAllQuery匹配所有;
termQuery精准匹配,大小写敏感且不支持;
matchPhraseQuery对中文精确匹配;
matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性;
multiMatchQuery("text", "field1", "field2"..); 匹配多个字段。

比如查询2021年10月25日之前位于海南省、广东省深圳市或广州市的用户数

"query": {
        "bool": {
            "must": [
                {
                    "range": {
                        "event.createDate": {
                            "from": null,
                            "to": "2021-10-25",
                            "include_lower": true,
                            "include_upper": true
                        }
                    }
                }
            ],
            "should": [
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "header.region": {
                                        "value": "海南省"
                                    }
                                }
                            }
                        ]
                    }
                },
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "header.region": {
                                        "value": "广东省"
                                    }
                                }
                            },
                            {
                                "terms": {
                                    "header.city": [
                                        "深圳市",
                                        "广州市"
                                    ]
                                }
                            }
                        ]
                    }
                }
            ],
            "minimum_should_match": 1
        }
    }

elasticsearch搜索拥有一种评分机制,比如在在进行文章关键词搜索时,可以设置标题title的boost=2,这样同时搜索标题title和正文content时,标题匹配就比较靠前了

"query": {
        "bool": {
            "should": [{
                "match": {
                    "title": {
                        "query": "faxwo",
                        "boost": 2
                    }
                }
            },
            {
                "match": {
                    "content": "faxwo"
                }
            }]
        }
    }

Go实现MySQL binlog与ES数据同步

安装Go

安装go的同时也需要安装git
wget https://golang.google.cn/dl/go1.15.2.linux-amd64.tar.gz
tar -C /usr/local -zxvf go1.15.2.linux-amd64.tar.gz
配置环境变量 vi /etc/profile
export GOROOT=/usr/local/go
export GOPATH=/www/wwwroot/web.com/app/go
export PATH=$PATH:/usr/local/go/bin
其中GOPATH为go的项目目录地址,对应目录内容
QQ截图20220814220026.png

修改MySQL binlog日志模式

go-mysql-elasticsearch 支持binlog的日志模式为row模式,因此建议配置MySQLbinlog需指定该模式
log-bin=mysql-bin
binlog_format=row

go-mysql-elasticsearch安装

go env -w GOPROXY=https://goproxy.cn
go get go get github.com/siddontang/go-mysql-elasticsearch
cd $GOPATH/src/github.com/siddontang/go-mysql-elasticsearch
make
如下为配置 river.toml

# MySQL 配置:地址,用户名,密码
my_addr = "192.168.3.66:3306"
my_user = "root"
my_pass = "root"

# Elasticsearch地址
es_addr = "192.168.3.66:9210"

# 存储数据的位置
data_dir = "/var"

# Inner Http status address
stat_addr = "192.168.3.66:12800"
stat_path = "/es"
# pseudo server id like a slave
server_id = 1001

# mysql or mariadb
flavor = "mysql"

# mysql备份文件,如果不设置或设置为空,则跳过
# mysqldump = "mysqldump"

# minimal items to be inserted in one bulk
bulk_size = 128

# force flush the pending requests if we don't have enough items >= bulk_size
flush_bulk_time = "200ms"

# Ignore table without primary key
skip_no_pk_table = false

# elasticsearch 与 mysql 同步时对应的数据库名称
# MySQL数据源,schema:数据库,tables:表
[[source]]
schema = "db_blog"
tables = ["archive"]

# 映射到es
[[rule]]
schema = "db_blog"
table = "archive"
# es的索引名
index = "archive"
type = "_doc"

启动

$GOPATH/src/github.com/siddontang/go-mysql-elasticsearch/bin/go-mysql-elasticsearch -config=/xxx/river.toml

标签: Elasticsearch, Go, kibana, solr, ES

添加新评论