ES分布式搜索引擎
ES核心
NRT 近实时
Cluster集群
Node节点
Index索引
索引类似于Mysql中的库
Type类型
类似Mysql中的表
Document:文档
类似于表中的一条数据
Field字段
好比关系型数据库中列的概念,一个document有一个或者多个field组成。
shard:分片
一台服务器,无法存储大量的数据,ES把一个index里面的数据,分为多个shard,分布式的存储在各个服务器上面。
replica:副本
一个分布式的集群,难免会有一台或者多台服务器宕机,如果我们没有副本这个概念。就会造成我们的shard发生故障,无法提供正常服务。
我们为了保证数据的安全,我们引入了replica的概念,可以保证我们数据的安全。
在ES集群中,我们一模一样的数据有多份,能正常提供查询和插/入的分片我们叫做 primary shard,其余的我们就管他们叫做 replica shard(备份的分片)
存储数据 === 搜索数据 === 分析数据
Elasticsearch 工作原理
ES索引有单个或集群的概念 单个索引是单独建立一个索引,集群则是多个节点,集群可以增加查询能力,可以提高扩展性和高可用性,当集群节点数量变化时Elasticsearch会自动迁移碎片以重新平衡集群。
分片:主分片(固定),副本分片(可更改)
性能取决于配置
分片的大小保持在几GB到十几GB之间,一个节点的容纳的分片数和可用空间成正比。每1GBd的分片数最好少于20个。
容灾
为减少时间消耗,尽可能在同一网络下创建截取节点。
CCR:跨集群复制—> 可以自动将索引从主集群同步到远程的辅助集群,主集群发生故障从集群可以接管
跨集群复制是主动 + 被动。主集群是主动索引,并处理所有写入请求,然后复制到从节点,从集群不做索引操作,只做接收。
运维
Kibana 一个可视化工具--》监控和管理
IK中文分词器
ik_smart:最少切分
ik_max_word为最细的粒度划分
ElasticSearch集群
ES集群是一个P2P类型的分布式系统,除了集群的状态管理以为外,其他所有的请求都可以发送到集群内任意一台节点上,配置相同的集群名称确定节点的集群。
ES集群的扩容问题
垂直扩容:垂直扩容就是把其中的一个节点换成性能更强的节点。
水平扩容:新增服务器节点(比较费钱)
对等式架构
大多数的分布式系统都是主从式架构,但是ES是对等式架构。
ES中主节点(master)的作用:
-
管理集群中的元数据,比如索引的创建,删除等。
-
集群中的master也是自动选举的。
HDFS是主从式架构,有namenode和datanode,数据在进行交互的过程中需要先和namenode进行数据交互然后才能和datanode进行数据交互。在ES中进行数据交互过程中不需要跟master进行交互,节点之间的关系都是对等的,每个节点都可以进行接收请求和响应请求。
每个ES里面都知道其他的数据存在哪,ES的节点会自动帮你把请求发到要查询数据的节点上。这样就真的查询出来了。而我们随意找的这个节点叫做协调节点,真正数据存放的节点会把数据返回给协调节点。协调节点再给我们java的代码
ES的primary shard和replica shard
-
index可以包含多个type,同样一个index下面也可以有多个shard。
-
在ES里面每个shard就是最小的工作单元,承载了部分数据。
-
如果在ES集群里面增加或减少节点,shard会自动的实现负载均衡。
-
primary shard进行都和写 replica shard负责读。
-
primary shard在创建index的时候就固定了,不能修改。
-
默认创建一个index的时候,primary shard的数量是5,replica的数量是1,也就是说默认情况下有10个shard,其中有5个primary shard,5个是replica shard
-
primary shard和自己的replice shard是不能在同一台服务器上的。
ES的容错机制
-
master的选举
-
replice的容错
-
数据恢复
import com.alibaba.fastjson.JSON;
import com.itjiaming.es_springboot.bean.User;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.BeforeClass;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.ArrayList;
@SpringBootTest
class EsSpringbootApplicationTests {
private static String INDEX_TEST = "index_test";
private static String TYPE_TEST = "type_test";
@Autowired
private RestHighLevelClient client;
/**
* @Description 创建索引
* @Param null
* @Return {@link null}
* @Author zhengjiaming
* @Date 2022/11/10 10:22
*/
@Test
void contextLoads() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("六脉神剑");
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
System.out.println(shardsAcknowledged);
client.close();
}
/*
* @Description 判断索引是否存在
* @Param null
* @Return {@link null}
* @Author zhengjiaming
* @Date 2022/11/10 10:21
*/
@Test
public void existsIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest();
request.indices("六脉神剑");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println("existsIndex: " + exists);
}
/**
* @Description 向索引里新增数据
* @Param null
* @Return {@link null}
* @Author zhengjiaming
* @Date 2022/11/10 10:27
*/
@Test
public void add() throws IOException {
ArrayList<User> userArrayList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
User user = new User();
user.setId(Long.valueOf(i));
user.setName("this is the test " + i);
userArrayList.add(user);
}
for (User user : userArrayList) {
IndexRequest indexRequest = new IndexRequest(INDEX_TEST, TYPE_TEST, user.getId().toString());
indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println("add: " + JSON.toJSONString(indexResponse));
}
}
/**
* @Description 查询文档
* @Param null
* @Return {@link null}
* @Author zhengjiaming
* @Date 2022/11/10 10:43
*/
@Test
public void get() throws IOException {
GetRequest getRequest = new GetRequest(INDEX_TEST, TYPE_TEST, "99");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println("get: " + JSON.toJSONString(getResponse));
}
}