Elasticsearch
1. Elasticsearch简介
Elasticsearch是一个基于Lucene的一个开源的分布式、RESTful 风格的搜索和数据分析引擎。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
2. Lucene 核心库
Lucene 可以说是当下最先进、高性能、全功能的搜索引擎库——无论是开源还是私有,但它也仅仅只是一个库。为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。 更糟糕的是,您可能需要获得信息检索学位才能了解其工作原理,因为Lucene 非常复杂。
为了解决Lucene使用时的繁复性,于是Elasticsearch便应运而生。它使用 Java 编写,内部采用 Lucene 做索引与搜索,但是它的目标是使全文检索变得更简单,简单来说,就是对Lucene 做了一层封装,它提供了一套简单一致的 RESTful API 来帮助我们实现存储和检索。
3. 和solr对比
ElasticSearch对比 Solr 总结
项目 | ES | Solr |
---|---|---|
安装 | 简单,开箱即用 | 复杂 |
分布式 | 自带分布式协调管理功能 | 利用zookeeper分布式管理 |
支持类型 | JSON | JSON,XML,CSV |
功能 | 注重核心功能,其他功能借助于第三方插件 | 提供功能更多 |
查询速度 | 建立索引快,查询慢,实时查询快,推特,新浪实时应用 | 查询快,增删改查慢,传统应用 |
社区 | 学习成本高,开发维护者少,更新快 | 社区成熟 |
4. 倒排索引(重点)
正排索引根据id 找到对应的一组数据 (B+tree 聚簇索引)
非聚簇索引:给一个字段建立索引,查询的时候 根据这个字段查到这行数据对应的id。回表,再根据id 去查 聚簇索引 从而拿到一行数据。
4.1正排索引
4.2 倒排索引
一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的 Term 列表。
4.3 分词
就是按照一定的规则,将一句话分成组合的单词,按照国人喜欢来进行的
海上生明月 - 如何分成 ----->海上 | 生 | 明月
4.4模拟一个倒排索引
原理步骤:
1. 将数据存入mysql之前,对其进行分词
2. 将分词和存入后得到的id,存放在数据结构中Map<String,Set<Integer>> index
1. 查询时先分词,然后从index中拿到Set<Integer> ids
1. 再根据ids 查询mysql,从而得到结果,这样借助了mysql的B+tree索引,提高性能
4.4.1创建项目
引入第三方结巴分词器依赖
<dependency>
<groupId>com.huaban</groupId>
<artifactId>jieba-analysis</artifactId>
<version>1.0.2</version>
</dependency>
4.4.2注入分词器
/**
* 往IOC容器中入住结巴分词组件
*
* @return
*/
@Bean
public JiebaSegmenter jiebaSegmenter() {
return new JiebaSegmenter();
}
4.4.3测试分词器
@Autowired
public JiebaSegmenter jiebaSegmenter;
@Test
void testJieBa() {
String words = "华为 HUAWEI P40 Pro 麒麟990 5G SoC芯片 5000万超感知徕卡四摄 50倍数字变焦 8GB+256GB零度白全网通5G手机";
// 使用结巴分词,对字符串进行分词,分词类型为搜索类型
List<SegToken> tokens = jiebaSegmenter.process(words, JiebaSegmenter.SegMode.INDEX);
// 遍历,拿到SegToken对象中的word属性,打印结果
tokens.stream()
.map(token -> token.word)
.collect(Collectors.toList())
.forEach(System.out::println);
}
5.商品搜索案例
使用倒排索引加分词器,展示商品搜索功能
5.1创建实体类Goods
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {
/**
* 商品的id
*/
private Integer goodsId;
/**
* 商品的名称(主要分词和检索字段)
*/
private String goodsName;
/**
* 商品的价格
*/
private Double goodsPrice;
}
5.2模拟数据库,新建DBUtil类
public class DBUtil {
/**
* 模拟数据库,key=id,value=商品对象
* 这里也可以使用List来模拟
*/
public static Map<Integer, Goods> db = new HashMap<>();
/**
* 插入数据库
*
* @param goods
*/
public static void insert(Goods goods) {
db.put(goods.getGoodsId(), goods);
}
/**
* 根据id得到商品
*
* @param id
* @return
*/
public static Goods getGoodsById(Integer id) {
return db.get(id);
}
/**
* 根据ids查询商品集合
*
* @param ids
* @return
*/
public static List<Goods> getGoodsByIds(Set<Integer> ids) {
if (CollectionUtils.isEmpty(ids)) {
return Collections.emptyList();
}
List<Goods> goods = new ArrayList<>(ids.size() * 2);
// 循环ids
ids.forEach(id -> {
// 从数据库拿到数据
Goods g = db.get(id);
if (!ObjectUtils.isEmpty(g)) {
goods.add(g);
}
});
return goods;
}
}
5.3创建GoodsService接口
public interface GoodsService {
/**
* 添加商品的方法
*
* @param goods
*/
void addGoods(Goods goods);
/**
* 根据商品名称查询
*
* @param name
* @return
*/
List<Goods> findGoodsByName(String name);
/**
* 根据关键字查询
*
* @param keywords
* @return
*/
List<Goods> findGoodsByKeywords(String keywords);
}
5.4模拟倒排索引类
//倒排索引
public class InvertedIndex {
//倒排索引key=分词, value=ids
public static Map<String, Set<Integer>> index=new HashMap<>();
}
5.5 创建GoodsServiceImpl实现类
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private JiebaSegmenter jiebaSegmenter;
/**
* 添加商品的方法
* 1.先对商品名称进行分词,拿到了List<String> tokens
* 2.将商品插入数据库 拿到商品id
* 3.将tokens和id放入倒排索引中index
*
* @param goods
*/
@Override
public void addGoods(Goods goods) {
// 分词
List<String> keywords = fenci(goods.getGoodsName());
// 插入数据库
DBUtil.insert(goods);
// 保存到倒排索引中
saveToInvertedIndex(keywords, goods.getGoodsId());
}
/**
* 保存到倒排索引的方法
*
* @param keywords
* @param goodsId
*/
private void saveToInvertedIndex(List<String> keywords, Integer goodsId) {
// 拿到索引
Map<String, Set<Integer>> index = InvertedIndex.index;
// 循环分词集合
keywords.forEach(keyword -> {
Set<Integer> ids = index.get(keyword);
if (CollectionUtils.isEmpty(ids)) {
// 如果之前没有这个词 就添加进去
HashSet<Integer> newIds = new HashSet<>(2);
newIds.add(goodsId);
index.put(keyword, newIds);
} else {
// 说明之前有这个分词 我们记录id
ids.add(goodsId);
}
});
}
/**
* 分词的方法
*
* @param goodsName
* @return
*/
private List<String> fenci(String goodsName) {
List<SegToken> tokens = jiebaSegmenter.process(goodsName, JiebaSegmenter.SegMode.SEARCH);
return tokens.stream()
.map(token -> token.word)
.collect(Collectors.toList());
}
/**
* 根据商品名称查询
*
* @param name
* @return
*/
@Override
public List<Goods> findGoodsByName(String name) {
// 查询倒排索引中 是否有这个词
Map<String, Set<Integer>> index = InvertedIndex.index;
Set<Integer> ids = index.get(name);
if (CollectionUtils.isEmpty(ids)) {
// 查询数据库 模糊匹配去
} else {
// 说明分词有 根据ids 查询数据库
return DBUtil.getGoodsByIds(ids);
}
return Collections.emptyList();
}
/**
* 根据关键字查询
*
* @param keywords
* @return
*/
@Override
public List<Goods> findGoodsByKeywords(String keywords) {
// 进来先把关键字分词一下
List<String> tokens = fenci(keywords);
// 拿到倒排索引
Map<String, Set<Integer>> index = InvertedIndex.index;
Set<Integer> realIds = new HashSet<>();
// 循环分词集合 查询倒排索引
tokens.forEach(token -> {
Set<Integer> ids = index.get(token);
if (!CollectionUtils.isEmpty(ids)) {
// 如果局部的ids不为空,就添加到总的ids里面去
realIds.addAll(ids);
}
});
// 查询数据库
return DBUtil.getGoodsByIds(realIds);
}
}
5.6编写测试类
@Test
public void testMyIndex() throws Exception {
// 造数据
Goods goods = new Goods(1, "苹果手机", 10.00);
Goods goods1 = new Goods(2, "华为手机", 11.00);
Goods goods2 = new Goods(3, "红米手机", 5.00);
Goods goods3 = new Goods(4, "联想手机", 6.00);
Goods goods4 = new Goods(5, "联想笔记本", 8916.00);
Goods goods5 = new Goods(6, "小米笔记本", 6983.5);
goodsService.addGoods(goods);
goodsService.addGoods(goods1);
goodsService.addGoods(goods2);
goodsService.addGoods(goods3);
goodsService.addGoods(goods4);
goodsService.addGoods(goods5);
// 查询
goodsService.findGoodsByName("苹果手机").forEach(System.out::println);
goodsService.findGoodsByKeywords("苹果小米联想").forEach(System.out::println);
}
6.Elasticsearch安装
下载地址 https://www.elastic.co/cn/downloads/past-releases#elasticsearch
使用比较新的版本7.15.2
6.1目录
bin:启动脚本
config:elasticsearch.yml,ES的集群信息、对外端口、内存锁定、数据目录、跨域访问等属性的配置
jvm.options,ES使用Java写的,此文件用于设置JVM相关参数,如最大堆、最小堆
log4j2.properties,ES使用log4j作为其日志框架
data:数据存放目录(索引数据)
plugins: ES的可扩展插件存放目录,如可以将ik中文分词插件放入此目录,ES启动时会自动加载
6.2 Elasticsearch可视化插件的安装
6.2.1谷歌插件方式
6.2.2解决跨域问题
如果是远程访问,涉及到跨域访问,报错,解决方式如下:
修改elasticsearch.yml配置文件
http.cors.enabled: true
http.cors.allow-origin: "*"
6.3IK分词的安装【重点】
Ik分词在es 里面也是插件的形式安装的
{
"analyzer":"standard",
"text":"我要学习java"
}
6.3.1安装分词器
- 找对应的ES版本的IK分词 https://github.com/medcl/elasticsearch-analysis-ik/releases
- 下载后拷贝到plugins目录下
- 重启测试
6.3.2分词器类型
Ik分词的两种方式:
ik_smart:分词的粒度较小,也叫智能分词
**ik_max_word:**分词的粒度较大,也叫最大力度分词
7.Elasticsearch核心概念【重点】
一个json串 叫文档 es又被叫文档性数据库
7.1 结构说明
Elasticsearch | Mysql |
---|---|
Index(索引库) | Database(数据库) |
Type(_doc) | Table(表) |
Document(文档) | Row(行) |
Field(字段) | Column(列) |
mappings | 列的类型约束(int,varchar…) |
这里的Type概念从ES6.x以后被弱化,官方将在ES8.0以后正式剔除了。
7.2 索引库(indices)
把数据写入elasticsearch 时,会在里面建立索引,索引库里面存储索引,一个index 对应一个database
7.3 文档(document)
就是一条数据,一般使用json 表示,和数据库对比,就是一行数据,在java 里面就是一个对象
7.4 字段(field)
一个对象的属性,对应数据库就是一列
7.5 节点
一台运行elasticsearch的服务器,被称为一个节点
7.6 集群
多个节点组成一个集群
7.7 分片
一个索引可以存储在多个主分片上,有负载均衡的作用,还有从分片是主分片的一个副本
7.8 副本
一份数据可以有多个副本,做数据冗余(安全),一般放在从分片里面
8. Elasticsearch基本使用(重点)
Elasticsearch 是基于restful风格的http应用,Restful风格就是使用http动词形式对url资源进行操作(GET,POST,PUT,DELETE…)
操作格式为:
请求类型 ip:port/索引名/_doc/文档id
{请求体}
8.1 对索引和mappings的操作(建库建表约束)
8.1.1 新增索引
PUT http://192.168.226.128:9200/student 新建一个student索引,给定几个字段约束,索引只能增删,不能修改
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
},
"birthDay":{
"type": "date"
},
"price":{
"type": "double"
}
}
}
}
8.1.2查询索引
8.1.3查询索引的mappings信息
8.1.4 删除索引
DELETE http://192.168.226.128:9200/student
8.2 对Document的操作
8.2.1 新增数据
使用put请求新增时需要自己指定id,使用post请求新增时系统会自动生成一个id
PUT http://192.168.226.128:9200/user/_doc/1
user: 索引名称
doc:类型(即将剔除,官方建议全部使用doc)
1: 文档id
从head插件里面查看数据
8.2.2 修改一个数据
- 危险的修改,把其他的字段值都删了
PUT http://192.168.226.128:9200/user/_doc/2
2.安全的修改,其他的字段值会保留
POST http://192.168.226.128:9200/user/_doc/2/_update
8.2.3 删除一个数据
DELETE http://192.168.226.128:9200/user/_doc/3
8.2.4查询一个数据
GET http://192.168.226.128:9200/user/_doc/1
8.2.5 查询全部数据
GET http://192.168.226.128:9200/user/_doc/_search
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaFtriAH-1671947370531)(images\26.png)]
9.SpringBoot使用ES【重点】
9.1创建项目,添加ES依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
9.2修改配置application.yml
spring:
elasticsearch:
uris: http://192.168.226.129:9200
9.3 测试连接ES
说明我们连接成功,下面开始操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tAEoIzNR-1671947370531)(C:\Users\mengyang\Documents\Elasticsearch\images\27.png)]
9.1 Java对索引的操作
9.1.1 新建Goods实体类
/**
* @Document是ES提供的注解 indexName:索引名称
* createIndex:启动时是否创建
* shards:分片个数
* replicas:副本个数
* refreshInterval:数据导入到索引里面,最多几秒搜索到
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Setting(shards = 2,replicas = 1,refreshInterval = "1s")
@Document(indexName = "goods_index")
public class Goods {
/**
* 商品ID
*/
@Id //默认使用keyword关键字模式,不进行分词
@Field
private Integer goodsId;
/**
* 商品名称
* analyzer:插入时使用的分词,如果不设置使用ES预设的
* searchAnalyzer:搜索时使用的分词,如果不设置使用analyzer,最后使用ES预设
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String goodsName;
/**
* 商品描述
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String goodsDesc;
/**
* 商品价格
*/
@Field(type = FieldType.Double)
private Double goodsPrice;
/**
* 商品的销量
*/
@Field(type = FieldType.Long)
private Long goodsSaleNum;
/**
* 商品的卖点
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String goodsBrief;
/**
* 商品的状态
*/
@Field(type = FieldType.Integer)
private Integer goodsStatus;
/**
* 商品的库存
*/
@Field(type = FieldType.Integer)
private Integer goodsStock;
/**
* 商品的标签
*/
@Field(type = FieldType.Text)
private List<String> goodsTags;
/**
* 上架的时间
* 指定时间格式化
*/
private Date goodsUpTime;
}
9.1.2对文档的操作即数据访问类
@Repository
public interface GoodsDao extends ElasticsearchRepository<Goods, Integer> {
}
9.1.3新增数据
@Autowired
private GoodsDao goodsDao;
@Test
public void testDocumentCurd() throws Exception {
//新增商品数据100条
ArrayList<Goods> goods = new ArrayList<>(200);
for (int i = 1; i <= 100; i++) {
goods.add(
new Goods(i,
i % 2 == 0 ? "华为电脑" + i : "联想电脑" + i,
i % 2 == 0 ? "轻薄笔记本" + i : "游戏笔记本" + i,
4999.9 + i,
999L,
i % 2 == 0 ? "华为续航强" : "联想性能强",
i % 2 == 0 ? 1 : 0,
666 + i,
i % 2 == 0 ? Arrays.asList("小巧", "轻薄", "续航") : Arrays.asList("炫酷", "畅玩", "游戏"),
new Date())
);
}
goodsDao.saveAll(goods);
}
9.1.4 修改数据(注意是危险修改)
@Test
public void testUpdate() throws Exception {
goodsDao.save(new Goods(1, "小米笔记本", null, null, null, null, null, null, null, null));
}
9.1.5删除数据
@Test
public void testDelete() throws Exception{
goodsDao.deleteById(1);
}
9.1.6根据Id查询数据
@Test
public void testSearchById() throws Exception {
Optional<Goods> byId = goodsDao.findById(502);
System.out.println(byId.get());
}
9.1.7查询所有数据
@Test
public void testSearchAll() throws Exception {
Iterable<Goods> all = goodsDao.findAll();
all.forEach(System.out::println);
}
10.复杂的查询操作【重点】
10.1 查询注意点
match:会通过分词器去模糊匹配 例如:华为电脑,会把包含‘华为’,‘电脑’,都查出来
matchPhrase:不分词查询,弥补了match和term
term:精确查找你的关键字,一般使用keywords的约束,使用term
rang:范围查询
match 和 rang 如果同时出现,需要组合bool查询
分页,排序是通用的查询,不需要通过bool组合使用,直接nativeSearchQueryBuilder使用
10.2 查询常用类
QueryBuilders:构造条件对象,例如matchQuery,rangeQuery,boolQuery等
NativeSearchQueryBuilder:组合条件对象,组合后使用build构建查询对象
HighlightBuilder:高亮的查询类,注意使用它的Field静态内部类
FunctionScoreQueryBuilder:权重类,注意它的FilterFunctionBuilder静态内部类
10.3关键字,范围,分页,排序
查询条件:商品名称为“华为",价格在5000-7000之间,按照价格降序排列,输出第一页,每页大小20条
@Test
public void testFuZaSearch() throws Exception {
//关键字,“华为”
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("goodsName", "华为");
//价格范围
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("goodsPrice").from(5000).to(7000);
//使用bool组合这两个查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().must(matchQueryBuilder).must(rangeQueryBuilder);
//创建组合查询器
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
//去build()构建查询对象
NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder
.withQuery(boolQueryBuilder)
.withPageable(PageRequest.of(0, 20)) //注意范围和分页有关系,可能查出来了,但是当前分页没有
.withSort(SortBuilders.fieldSort("goodsPrice").order(SortOrder.ASC))
.build();
//使用es查询 得到结果集
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
searchHits.forEach(goodsSearchHit -> {
//循环结果集,输出
System.out.println(goodsSearchHit.getContent());
});
}
10.4高亮查询
查询名称包含“华为“的产品,将"goodsName"设置为高亮字段,添加”字体红色“样式,将查询命中的数据循环,
并将高亮字段的值赋给"goodsName"
@Test
public void testHighlight() throws Exception {
//华为,模糊匹配
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("goodsName", "华为");
HighlightBuilder.Field goodsName = new HighlightBuilder.Field("goodsName").preTags("<span style='color:red'>").postTags("</span>");
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder
.withQuery(matchQueryBuilder)
.withHighlightFields(goodsName)
.build();
//得到结果集 我们需要手动组装高亮字段
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
List<Goods> goodsArrayList = new ArrayList<>();
searchHits.forEach(goodsSearchHit -> {
//得到goods对象,但是这里面goodsName属性不是高亮的,所以要改
Goods goods = goodsSearchHit.getContent();
List<String> highlightField = goodsSearchHit.getHighlightField("goodsName");
String highlight = highlightField.get(0);
//将高亮的商品名称赋给goods对象
goods.setGoodsName(highlight);
goodsArrayList.add(goods);
});
System.out.println(JSON.toJSONString(goodsArrayList));
}
}
10.5权重查询
@Test
public void testWeight() throws Exception {
//根据产品名称和产品介绍进行查询,谁的权重高,排名在前
//创建权重数组
FunctionScoreQueryBuilder.FilterFunctionBuilder[] functionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[2];
//设置权重
functionBuilders[0] = (new FunctionScoreQueryBuilder.FilterFunctionBuilder(
QueryBuilders.matchQuery("goodsName", "华为"),
ScoreFunctionBuilders.weightFactorFunction(6)//给名称设置10的权重大小
));
functionBuilders[1] = (
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
QueryBuilders.matchQuery("goodsBrief", "联想"),
ScoreFunctionBuilders.weightFactorFunction(10)//给卖点设置4的权重
));
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(functionBuilders);
functionScoreQueryBuilder.setMinScore(2) //设置最小分数
.scoreMode(FunctionScoreQuery.ScoreMode.FIRST);//设置计分方式
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(functionScoreQueryBuilder).build();
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
searchHits.forEach(goodsSearchHit -> {
//循环结果集,打印结果
System.out.println(goodsSearchHit.getContent());
});
}
11. ES集群(了解)
这里使用windows方式演示集群,Linux上的集群道理一样,修改配置文件即可
可以参考https://my.oschina.net/u/4353003/blog/4333773
11.1创建三个es节点
11.2 修改配置文件
11.2.1 Node1修改配置文件
进入elasticsearch-7.15.2-node1\config下,修改elasticsearch.yml
# 设置集群名称,集群内所有节点的名称必须一致。
cluster.name: my-esCluster
# 设置节点名称,集群内节点名称必须唯一。
node.name: node1
# 表示该节点会不会作为主节点,true表示会;false表示不会
node.master: true
# 当前节点是否用于存储数据,是:true、否:false
node.data: true
# 索引数据存放的位置
#path.data: /opt/elasticsearch/data
# 日志文件存放的位置
#path.logs: /opt/elasticsearch/logs
# 需求锁住物理内存,是:true、否:false
#bootstrap.memory_lock: true
# 监听地址,用于访问该es
network.host: 0.0.0.0
# es对外提供的http端口,默认 9200
http.port: 9200
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9300
# 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
discovery.zen.minimum_master_nodes: 2
# es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.186.1:9300", "192.168.186.1:9301", "192.168.186.1:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
# es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node1", "node2", "node3"]
# 是否支持跨域,是:true,在使用head插件时需要此配置
http.cors.enabled: true
# “*” 表示支持所有域名
http.cors.allow-origin: "*"
action.destructive_requires_name: true
action.auto_create_index: .security,.monitoring*,.watches,.triggered_watches,.watcher-history*
xpack.security.enabled: false
xpack.monitoring.enabled: true
xpack.graph.enabled: false
xpack.watcher.enabled: false
xpack.ml.enabled: false
11.2.2 Node2修改配置文件
# 设置集群名称,集群内所有节点的名称必须一致。
cluster.name: my-esCluster
# 设置节点名称,集群内节点名称必须唯一。
node.name: node2
# 表示该节点会不会作为主节点,true表示会;false表示不会
node.master: true
# 当前节点是否用于存储数据,是:true、否:false
node.data: true
# 索引数据存放的位置
#path.data: /opt/elasticsearch/data
# 日志文件存放的位置
#path.logs: /opt/elasticsearch/logs
# 需求锁住物理内存,是:true、否:false
#bootstrap.memory_lock: true
# 监听地址,用于访问该es
network.host: 0.0.0.0
# es对外提供的http端口,默认 9200
http.port: 9201
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9301
# 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
discovery.zen.minimum_master_nodes: 2
# es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.186.1:9300", "192.168.186.1:9301", "192.168.186.1:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
# es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node1", "node2", "node3"]
# 是否支持跨域,是:true,在使用head插件时需要此配置
http.cors.enabled: true
# “*” 表示支持所有域名
http.cors.allow-origin: "*"
action.destructive_requires_name: true
action.auto_create_index: .security,.monitoring*,.watches,.triggered_watches,.watcher-history*
xpack.security.enabled: false
xpack.monitoring.enabled: true
xpack.graph.enabled: false
xpack.watcher.enabled: false
xpack.ml.enabled: false
11.2.3 Node3修改配置文件
# 设置集群名称,集群内所有节点的名称必须一致。
cluster.name: my-esCluster
# 设置节点名称,集群内节点名称必须唯一。
node.name: node3
# 表示该节点会不会作为主节点,true表示会;false表示不会
node.master: true
# 当前节点是否用于存储数据,是:true、否:false
node.data: true
# 索引数据存放的位置
#path.data: /opt/elasticsearch/data
# 日志文件存放的位置
#path.logs: /opt/elasticsearch/logs
# 需求锁住物理内存,是:true、否:false
#bootstrap.memory_lock: true
# 监听地址,用于访问该es
network.host: 0.0.0.0
# es对外提供的http端口,默认 9200
http.port: 9202
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9302
# 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
discovery.zen.minimum_master_nodes: 2
# es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.186.1:9300", "192.168.186.1:9301", "192.168.186.1:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
# es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node1", "node2", "node3"]
# 是否支持跨域,是:true,在使用head插件时需要此配置
http.cors.enabled: true
# “*” 表示支持所有域名
http.cors.allow-origin: "*"
action.destructive_requires_name: true
action.auto_create_index: .security,.monitoring*,.watches,.triggered_watches,.watcher-history*
xpack.security.enabled: false
xpack.monitoring.enabled: true
xpack.graph.enabled: false
xpack.watcher.enabled: false
xpack.ml.enabled: false
11.3 启动es
进入bin目录下 逐个启动,三台全部双击启动,注意不要关闭黑窗口
11.4 访问查看集群信息和状态
访问查看:http://127.0.0.1:9200/_cat/nodes
也可以使用head插件查看
11.5SpringBoot连接ES集群
spring:
elasticsearch:
uris:
- http://127.0.0.1:9200
- http://127.0.0.1:9201
- http://127.0.0.1:9202