es入门使用

James 2020年11月22日 139次浏览

安装

  1. 下载,这里使用7.10.0版本,如有需要,可前往官网自行下载
  2. 解压:tar -zxvf elasticsearch-7.10.0-linux-x86_64.tar.gz
  3. 将解压的目录移动到/usr/local/elasticsearchmv elasticsearch-7.10.0 /usr/local/elasticsearch,个人习惯将软件安装到该目录下,嘿嘿。
  4. 进入到配置目录进行配置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"]
  1. 由于我们使用的服务器内存较小,我们可以将es运行所需使用的内存调小一点,避免启动出现问题,在jvm.options文件中修改两个属性即可。如下:
-Xms128m
-Xmx128m
  1. 创建用户,由于es不能使用root用户进行启动,所以我们需要创建一个es专门的用户。
useradd esuser
chown -R esuser:esuser /usr/local/elasticsearch
  1. 切换到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

这里出现了两个问题

  1. 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
  1. 最大虚拟内存区域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中文分词器。

  1. 首先肯定是下载,下载请点击这里,根据自己es的版本下载对应的中文分词器。
  2. 解压到es的安装目录下的plugins文件夹下,例如:unzip elasticsearch-analysis-ik-7.10.0.zip -d /usr/local/elasticsearch/plugins/ik
  3. 有时候我们需要扩展自己的词库,比如说网络用词,商标,公司名等。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,肯定是需要先安装的。步骤如下:

  1. 下载
  2. 解压到/usr/local/logstash下,tar -zxvf logstash-7.10.0-linux-x86_64.tar.gz -C /usr/local/logstash
  3. 创建一个工作目录,用于配置logstash的数据采集来源及数据输出去向,mkdir /usr/local/logstash/work && cd /usr/local/logstash/work
  4. 以上是logstash的安装,接下来我们需要配置规则,要讲db的数据同步到es中需要使用logstash-jdbc-input插件,该插件在新版本中已经内置了,所以无需安装,只需要一个数据库的驱动文件就OK了,这里我们使用的数据库是mysql,所以需要提前准备一个jar包(我们可以从这里找到对应的版本进行下载)。并且将jar包copy到work目录下待用。
  5. 创建一个sql文件,用于logstash进行数据采集,例如:
cat > /usr/local/logstash/work/goods.sql <<EOF
select * from goods where id > :sql_last_value
EOF
  1. 创建一个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
    }
}
  1. 启动./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.namecluster.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有该配置的节点数。