安装
- 下载,这里使用7.10.0版本,如有需要,可前往官网自行下载
- 解压:
tar -zxvf elasticsearch-7.10.0-linux-x86_64.tar.gz
- 将解压的目录移动到
/usr/local/elasticsearch
中mv elasticsearch-7.10.0 /usr/local/elasticsearch
,个人习惯将软件安装到该目录下,嘿嘿。 - 进入到配置目录进行配置
cd /usr/local/elasticsearch/config
,配置内容大致如下:
cluster.name: es-cluster
node.name: es-node1
path.data: /usr/local/elasticsearch/data
path.logs: /usr/local/elasticsearch/logs
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["es-node1"]
- 由于我们使用的服务器内存较小,我们可以将es运行所需使用的内存调小一点,避免启动出现问题,在jvm.options文件中修改两个属性即可。如下:
-Xms128m
-Xmx128m
- 创建用户,由于es不能使用root用户进行启动,所以我们需要创建一个es专门的用户。
useradd esuser
chown -R esuser:esuser /usr/local/elasticsearch
- 切换到esuser用户进行启动es,切换用户:
su esuser
,启动es:./bin/elasticsearch
错误解决
我们在第一次启动ES的时候,报了如下错误:
ERROR: [2] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
ERROR: Elasticsearch did not exit normally - check the logs at /usr/local/elasticsearch/logs/es-cluster.log
这里出现了两个问题
- elasticsearch进程的最大文件描述符[4096]太低,请至少增加到[65535]
解决办法:切换回root用户,编辑/etc/security/limits.conf
配置文件,追加内容:
# esuser为es用户,可以使用*号代替
esuser hard nofile 65536
esuser soft nofile 65536
esuser soft nproc 4096
esuser hard nproc 4096
# End of file
- 最大虚拟内存区域vm.max_map_count[65530]太低,至少增加到[262144]
解决办法:切换到root用户,在/etc/sysctl.conf
配置文件末尾追加一行配置vm.max_map_count=262144
,最后执行sysctl -p
使其立即生效。
示例
所有示例我用Talend API Tester进行测试,如果大家也熟悉使用该插件,可以下载该文件进行导入查看。
IK中文分词器
elasticsearch默认支持standard、simple、withspace、stop、keyword五种分词器,但是都不支持中文分词,所以我们需要手动安装一个中文分词器的插件。
在安装IK插件之前,先了解一下es中自带的五种分词器:
- standard:标准分词器,默认使用该分词器;该分词器会按词进行分词,且全部转为小写。例如:"My name is james,I'm from China!"这段话会被分词为"my/name/is/james/i'm/from/china"。
- simple:简单分词器,该分词器按非字母切分,且全部转小写。例如:"My name is james,I'm from China!"这段话会被分词为"my/name/is/james/i/m/from/china",和上面例子区别在于i'm
- withspace:按空格切分。例如:"My name is james,I'm from China!"这段话会被分词为"My/name/is/james,i'm/from/China!"。
- stop:和simple类似,但是该分词器会将组词等一些没有实际语义的词过滤掉。例如:"My name is james,I'm from China!"这段话会被分词为"my/name/james/i/m/from/china"。
- keyword:不进行分词,将一段话作为关键字。例如:"My name is james,I'm from China!"这段话会被分词为"My name is james,I'm from China!"。
以上就是es内置的五种分词器,这五种对于一个中文为主的应用来讲,达不到我们想要的效果,接下来安装IK中文分词器。
- 首先肯定是下载,下载请点击这里,根据自己es的版本下载对应的中文分词器。
- 解压到es的安装目录下的plugins文件夹下,例如:
unzip elasticsearch-analysis-ik-7.10.0.zip -d /usr/local/elasticsearch/plugins/ik
- 有时候我们需要扩展自己的词库,比如说网络用词,商标,公司名等。IK支持我们自己配置扩展字典,在
/usr/local/elasticsearch/plugins/ik/config
目录下的IKAnalyzer.cfg.xml
配置文件中进行配置,改配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
支持本地和远程的方式自定义扩展字典库。
重启es即完成了IK中文分词器的安装。后面在使用的时候就可以指定分词器为ik_max_word
/ik_smart
。安装完成后我们可以测试一下分词
curl -i -X POST \
-H "Content-Type:application/json" \
-d \
'{
"text":"就让秋风带走我的思恋",
"analyzer":"ik_smart"
}' \
'http://114.67.166.241:9200/_analyze'
ElasticSearch Rest API
创建索引
curl -i -X PUT \
-H "Content-Type:application/json" \
-d \
'{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"max_result_window": 1000
},
"mappings": {
"properties": {
"id": {
"type": "long",
"index": false
},
"goodsName": {
"type": "text",
"index": true,
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"goodsDesc": {
"type": "text",
"index": true
},
"goodsCategory": {
"type": "text",
"index": true
},
"goodsImg": {
"type": "text",
"index": false
},
"goodsPrice": {
"type": "double",
"index": false
},
"publishTime": {
"type": "date",
"index": false
}
}
}
}' \
'http://114.67.166.241:9200/goods'
数据同步
es搭建好了过后,我们不光是客户端应用需要接入使用es进行搜索,还需要将DB里面的数据同步到es中,es的数据同步有很多种方案,比如同步双写(在应用客户端上面写入DB的同时将数据也写入到es,改方式有很多缺点,比如性能上的损耗,当es出现问题时会导致db数据事务提交不成功等等的问题)、异步双写(该种方案比第一种方案好上不少,但也有一些缺点,比如耦合度太高,当然第一种方式也是强耦合的,实现复杂化)等等,这里我们使用logstash进行数据的同步,logstash本身也是elasticsearch官方发布的用于数据采集的工具。
当然了,需要使用logstash,肯定是需要先安装的。步骤如下:
- 下载
- 解压到
/usr/local/logstash
下,tar -zxvf logstash-7.10.0-linux-x86_64.tar.gz -C /usr/local/logstash
- 创建一个工作目录,用于配置logstash的数据采集来源及数据输出去向,
mkdir /usr/local/logstash/work && cd /usr/local/logstash/work
- 以上是logstash的安装,接下来我们需要配置规则,要讲db的数据同步到es中需要使用logstash-jdbc-input插件,该插件在新版本中已经内置了,所以无需安装,只需要一个数据库的驱动文件就OK了,这里我们使用的数据库是mysql,所以需要提前准备一个jar包(我们可以从这里找到对应的版本进行下载)。并且将jar包copy到work目录下待用。
- 创建一个sql文件,用于logstash进行数据采集,例如:
cat > /usr/local/logstash/work/goods.sql <<EOF
select * from goods where id > :sql_last_value
EOF
- 创建一个logstash的配置文件,这里命名为
db-sync-es.conf
,配置内容为:
input {
jdbc {
# mysql 数据库链接,shop为数据库名
jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/test"
# 用户名和密码
jdbc_user => "root"
jdbc_password => "root"
# 驱动
jdbc_driver_library => "/usr/local/logstash/work/mysql-connector-java-5.1.38.jar"
# 驱动类名
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "1000"
# 执行的sql 文件路径+名称
statement_filepath => "/usr/local/logstash/work/goods.sql"
# 设置监听间隔 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
schedule => "* * * * *"
# 是否记录上次执行结果, 如果为真,将会把上次执行到的 tracking_column 字段的值记录下来,保存到 last_run_metadata_path 指定的文件中
record_last_run => "true"
# 是否需要记录某个column 的值,如果record_last_run为真,可以自定义我们需要 track 的 column 名称,此时该参数就要为 true. 否则默认 track 的是 timestamp 的值.
use_column_value => "true"
# 如果 use_column_value 为真,需配置此参数. track 的数据库 column 名,该 column 必须是递增的. 一般是mysql主键
tracking_column => "id"
last_run_metadata_path => "/usr/local/logstash/work/last_id"
# 是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
clean_run => "false"
# 是否将 字段(column) 名称转小写
lowercase_column_names => "false"
}
}
output {
elasticsearch {
# ES的IP地址及端口
hosts => ["localhost:9200"]
# 索引名称
index => "goods"
# es中文档的id使用db中的id,保持一致
document_id => "%{id}"
# 在新版本中逐渐去除type,目前默认为_doc
document_type => "_doc"
}
stdout {
# JSON格式输出
codec => json_lines
}
}
- 启动
./logstash -f /usr/local/logstash/work/db-sync-es.conf
跨域
当我们在使用一些第三方管理界面(例如elasticsearch head)的时候可能会出现跨域问题,这里推荐使用head的chrome插件,因为插件其实是运行在chrome的扩展程序里面的,并不是浏览器上,它和直接URL请求是又区别的。使用chrome插件的方式运行head是不会出现跨域问题的。那么如果出现跨域问题我们也得想办法解决才行,其实只需要在elasticsearch.yml配置文件中配置如下内容即可:
http.cors.enabled:true
http.cors.allow-origin: "*"
集群搭建
elasticsearch集群搭建很简单,在之前安装好elasticsearch的基础上只需要添加几个配置即可,这里搭建一个三节点的es集群。主要配置如下:
cluster.name: es-cluster
node.name: es-node1
node.master: true
node.data: true
discover.seed_hosts: ["192.168.3.101","192.168.3.102","192.168.3.103"]
// 初始一个master节点
cluster.initial_master_nodes: es-node1
以上是es-node1节点的配置,其他两个节点的配置只需要修改node.name
和cluster.initial_master_nodes
,其他配置和es-node1节点保持一致即可。
将node.name
配置为es-node2/es-node3;cluster.initial_master_nodes
配置为es-node1,重启三个节点即完成es的集群搭建。
集群脑裂问题分析
什么是脑裂,一个集群中出现了多个Master从而导致集群分裂,为什么会出现脑裂问题,有时候可能是网络的原因,导致Master和Slave一时间联系不上,这个时候集群认为Master挂了,并且进行了新一轮的选举,然后或许在某一时刻网络又通了,原来的Master和集群能通信了,这个时候集群中出现了两个Master。这个时候在处理客户端请求时会出现分歧。
找到了问题的原因,应该如何去避免,这才是关键。其实,我们可以将discovery.zen.minimum_master_nodes
配置的值改成(n/2)+1
,这里n表示集群中有资格成为Master节点的数量,也就是node.master: true
有该配置的节点数。