环境准备
jdk版本
[root@iz2zefc352jeey9szh60wlz ~]# java -version
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
Linux操作系统
[root@iz2zefc352jeey9szh60wlz ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
ElasticSearch版本
elasticsearch-7.6.2-linux-x86_64.tar.gz
服务器(三台)
115.29.193.155
121.5.111.192
182.92.6.145
安装及测试(先三台各自独立启动测试)
下载
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-linux-x86_64.tar.gz
解压
tar -zxvf elasticsearch-7.6.2-linux-x86_64.tar.gz
mv elasticsearch-7.6.2 /usr/local
修改配置文件
cd /usr/local/elasticsearch-7.6.2/
vim config/elasticsearch.yml
具体修改项(对于单台独立启动,下面的配置暂且够用):
cluster.name: my-application #集群名称
node.name: node-1 #当前节点名称
#数据和日志的存储目录
path.data: /usr/local/elasticsearch-7.6.2/data
path.logs: /usr/local/elasticsearch-7.6.2/logs
#设置绑定的ip,设置为0.0.0.0以后就可以让任何计算机节点访问到了
network.host: 0.0.0.0
http.port: 9200 #端口
#设置在集群中的所有节点名称,这个节点名称就是之前所修改的,当然你也可以采用默认的也行,目前是单机,放入一个节点即可
cluster.initial_master_nodes: ["node-1"]
上面看到配置了一个数据目录,这个需要我们自己创建
mkdir data
默认给ElasticSearch配置的JVM内存很高,我服务器内存太小了,会跑不起的。所以改小一点。
vim config/jvm.options
改成
-Xms256m
-Xmx256m
root用户默认是无法启动elasticsearch的,所以需要增加一个Linux用户
useradd elasticsearch
chown elasticsearch /usr/local/elasticsearch-7.6.2/ -R
修改sysctl文件:vim /etc/sysctl.conf ,增加下面配置项
vm.max_map_count=262144
使其生效
sysctl -p
修改文件:vim /etc/security/limits.conf ,增加下面配置项
elasticsearch soft nproc 65565
elasticsearch hard nproc 65565
切换用户
su elasticsearch
查看进程数
ulimit -Hu
ulimit -Su
启动(-d 是后台启动)
/usr/local/elasticsearch-7.6.2/bin/elasticsearch -d
访问,大功告成~
[elasticsearch@iz2zefc352jeey9szh60wlz elasticsearch-7.6.2]$ curl 127.0.0.1:9200
{
"name" : "node-1",
"cluster_name" : "my-application",
"cluster_uuid" : "tkwKzDHuRSSURkA3jnljqQ",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
安装上面的步骤。配置完剩下俩台
集群化配置(将上面三台关连起来)
必要字段解释
cluster.name: my-application # 集群名字,用于将同一个集群的结点关连起来
node.name: "node-1" # 当前结点的名字,用于区分同一个集群中的结点
node.master: false # 在其它主结点宕机的情况下,是否有被选举成为主结点的资格
node.data: false # 当前结点存储数据
network.host: 0.0.0.0 #让所有网络都可以访问
http.port: 9200 #针对开发人员使用的端口
discovery.zen.ping.timeout: 60s # 用于发现其它结点的超时时间
transport.tcp.port: 9300 # 配置结点之间的客户端端口,下面就使用到
#discovery.zen.ping.unicast.hosts: ["localhost:9300"] # 其它结点的IP 这个版本6.x用的
discovery.seed_hosts: ["localhost:9300"] # 其它结点的IP 这个版本7.x用的(因为当前就是7.x所以用这个)
cluster.initial_master_nodes: ["localhost"] #填master结点有资格的备选结点
network.publish_host: 182.92.6.145 # 必填!!!必填,外网IP,否则集群无法关联起来
http.cors.enabled: true
http.cors.allow-origin: "*" # 跨域配置
discovery.zen.fd.ping_timeout: 1000s # 用于发现其它主机的发现时间,可以设置长一点防止网络不好就导致连接超时异常而失败
discovery.zen.fd.ping_retries: 10
182.92.6.145
data与master都设置为false就是用来做负载均衡服务器用。
cluster.name: my-application #集群名称
node.name: node-1 #当前节点名称
#数据和日志的存储目录
path.data: /usr/local/elasticsearch-7.6.2/data
path.logs: /usr/local/elasticsearch-7.6.2/logs
##设置绑定的ip,设置为0.0.0.0以后就可以让任何计算机节点访问到了
network.host: 0.0.0.0
http.port: 9200 #端口
##设置在集群中的所有节点名称,这个节点名称就是之前所修改的,当然你也可以采用默认的也行,目前是单机,放入一个节点即可
discovery.seed_hosts: ["182.92.6.145:9300","121.5.111.192:9300","115.29.193.155:9300"]
cluster.initial_master_nodes: ["182.92.6.145","121.5.111.192","115.29.193.155"]
## ping超时时长,默认3S,适当修改,防止脑裂
discovery.zen.fd.ping_timeout: 1000s
discovery.zen.fd.ping_retries: 10
network.publish_host: 182.92.6.145
http.cors.enabled: true
http.cors.allow-origin: "*"
transport.tcp.port: 9300
#discovery.zen.ping.unicast.hosts: ["182.92.6.145:9300", "121.5.111.192:9300","115.29.193.155:9300"]
discovery.zen.minimum_master_nodes: 2
115.29.193.155
针对上面需要改变的地方
node.name: node-2 #当前节点名称
network.publish_host: 115.29.193.155
121.5.111.192
针对上面需要改变的地方
node.name: node-3 #当前节点名称
network.publish_host: 121.5.111.192
最后分别启动即可
测试
浏览器输入:http://xiaowuqin.cn:9200/_cat/nodes访问即可,如下:
调式过程中踩坑记录
1.如果第一次启动elasticsearch用的root用户
如果第一次启动没有切换到其它用户,那么第二次尽管切换到了其它用户,依然会启动不了。
因为logs目录下的文件有几个被加载到了root用户下,其它用户没有权限执行读写,就会报错。
解决:改变文件所属用户为当前用户就行了。
chgrp -R es my-elasearch_server.json
chown -R es my-elasearch_server.json
...
2. 版本7.x相比6.x配置区别
相较于6.x配置文件 7.x的如下
cluster.initial_master_nodes: # 是7.x新引入的配置(配置候选主节点集合)
discovery.seed_hosts: # 对应旧版本的discovery.zen.ping.unicast.hosts(用于发现其它结点)
3.必配置项,如果不配置,会导致结点之间无法关联起来组成集群
network.publish_host: 115.29.193.155 # 当前结点的云服务器的外网IP
4.如果之前分别单独启动了结点
然后分别完成修改配置文件(改成了将单个结点关联起来的集群化配置),需要分别将它们的data目录删除掉才能启动成功。(data目录不存在它会自己创建)。这里的data目录相当于有了一个缓存需要清除。
参数调优
swap调优
首先明白什么是swap?
从性能上来说,swap上的数据读写速度不如RAM内存
从应用的运行稳定性上来说,swap相当于是一个保险。保险一般用不上,但是如果没有,真正发生意外的时候又后悔莫及。
从LInux的内核机制来说,要尽量保证每一个运行的应用都可以正常运行。因此当一个新的应用请求内存空间时,如果当时的内存空间不太够时,就会触发swap机制,让一些不常用的已经加载到内存中的文件回收进swap,从而释放出内存给新来的应用使用。而这个回收进swap的文件要再次被使用的时候,就会又重新加载到内存,这就称为swap交换。
而这elasticsearch为了实现极高的读写速度,就要尽量避免这种swap交换,影响性能。
如何配置swap?
yml中加入配置:
bootstrap.memory_lock: true # 单单从字母意思上就可以看出锁住内存,不让交换
修改/etc/security/limits.conf (因为是修改系统级配置,要使用root用户)
加入:
elasticsearch hard memlock unlimited
elasticsearch soft memlock unlimited
springboot整合及使用
新建一个springboot项目(然后勾选一个web就行了)
引入依赖(注意版本号一定要与你实际部署的一致,我的是7.6.2)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
另外注意这里的版本也要确认真的加载进来的是一致的版本号
如果不一样就配置这个,自定义
<!-- 自己定义elasticsearch版本-->
<elasticsearch.version>7.6.2</elasticsearch.version>
代码
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("115.29.193.155", 9200, "http"),
new HttpHost("121.5.111.192", 9200, "http"),
new HttpHost("182.92.6.145", 9200, "http")));
MainResponse info = client.info(RequestOptions.DEFAULT);
System.out.println("集群名字:"+info.getClusterName());
System.out.println("当前获得的结点名字"+info.getNodeName());
client.close();
运行结果
可以看到获取到的是node-2结点,然后我去把node-2 kill-9掉,模拟下宕机
再次获取,发现获取到的是node-3了,好了收工~
最后附上多条件查询及高亮代码demo
SearchRequest request = new SearchRequest("xiaowuqin");
//构建搜索条件
SearchSourceBuilder builder = new SearchSourceBuilder();
//分页
// builder.from(0);
// builder.size(10);
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.preTags("<span style='color:red;'>");
highlightBuilder.postTags("</span>");
builder.highlighter(highlightBuilder);
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//分词匹配
MatchQueryBuilder query = QueryBuilders.matchQuery("name", "山芯");
TermQueryBuilder query1 = QueryBuilders.termQuery("age", 3);
boolQueryBuilder.should(query1);
boolQueryBuilder.should(query);//多条件的或查询
//条件封装
//SearchSourceBuilder source = builder.query(query);
SearchSourceBuilder source = builder.query(boolQueryBuilder);
request.source(source);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = search.getHits();
SearchHit[] hits1 = hits.getHits();
for(SearchHit t:hits1){
//关键字高亮
Map<String, HighlightField> highlightFields = t.getHighlightFields();
HighlightField name = highlightFields.get("name");
Map<String, Object> sourceAsMap = t.getSourceAsMap();//原来的结果
//解析高亮字段
if(name!=null){
Text[] fragments = name.fragments();
String newname="";
for(Text tt:fragments){
newname+=tt;
}
sourceAsMap.put("name",newname);
}
System.out.println(sourceAsMap);