Elasticsearch集群

149 阅读6分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

集群的结构

单点的问题

单点的elasticsearch存在哪些可能出现的问题呢?

  • 单台机器存储容量有限,无法实现高存储
  • 单服务器容易出现单点故障,无法实现高可用
  • 单服务的并发处理能力有限,无法实现高并发

所以,为了应对这些问题,需要对elasticsearch搭建集群

数据分片

首先,面临的第一个问题就是数据量太大,单点存储量有限的问题。

可以把数据拆分成多份,每一份存储到不同机器节点(node),从而实现减少每个节点数据量的目的。这就是数据的分布式存储,也叫做:数据分片(Shard)

数据备份

数据分片解决了海量数据存储的问题,但是如果出现单点故障,那么分片数据就不再完整,这又该如何解决呢?

可以给每个分片数据进行备份,存储到其它节点,防止数据丢失,这就是数据备份,也叫数据副本(replica)

数据备份可以保证高可用,但是每个分片备份一份,所需要的节点数量就会翻一倍,成本实在是太高了!

为了在高可用和成本间寻求平衡,可以这样做:

  • 首先对数据分片,存储到不同节点
  • 然后对每个分片进行备份,放到对方节点,完成互相备份

这样可以大大减少所需要的服务节点数量

搭建集群

集群需要多台机器,这里用一台机器来模拟,因此需要在一台虚拟机中部署多个elasticsearch节点,每个elasticsearch的端口都必须不一样。

一台机器进行模拟:将ES的安装包复制三份,修改端口号,data和log存放位置的不同。

实际开发中:将每个ES节点放在不同的服务器上。

集群名称为:lagou-elastic,部署3个elasticsearch节点,分别是:

  • node-01:http端口9201,TCP端口9301
  • node-02:http端口9202,TCP端口9302
  • node-03:http端口9203,TCP端口9303

http:表示使用http协议进行访问时使用 端口,elasticsearch-head、kibana、postman,默认端口号是9200。

tcp:集群间的各个节点进行通讯的端口,默认9300

第一步:复制es软件粘贴3次,分别改名

image.png

第二步:修改每一个节点的配置文件confifig下的elasticsearch.yml,下面已第一份配置文件为例

三个节点的配置文件几乎一致,除了:node.name、path.data、path.log、http.port、transport.tcp.port

node-01:

#允许跨域名访问
http.cors.enabled: true
#当设置允许跨域,默认为*,表示支持所有域名
http.cors.allow-origin: "*"
#允许所有节点访问
network.host: 0.0.0.0
# 集群的名称,同一个集群下所有节点的集群名称应该一致
cluster.name: lagou-elastic
#当前节点名称 每个节点不一样
node.name: node-01
#数据的存放路径 每个节点不一样,不同es服务器对应的data和log存储的路径不能一样
path.data: d:\class\es-9201\data
#日志的存放路径 每个节点不一样
path.logs: d:\class\es-9201\logs
# http协议的对外端口 每个节点不一样,默认:9200
http.port: 9201
# TCP协议对外端口 每个节点不一样,默认:9300
transport.tcp.port: 9301
#三个节点相互发现,包含自己,使用tcp协议的端口号
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
#声明大于几个的投票主节点有效,请设置为(nodes / 2) + 1
discovery.zen.minimum_master_nodes: 2
# 是否为主节点
node.master: true

第三步:启动集群

把三个节点分别启动,启动时不要着急,要一个一个的启动

使用head插件查看:

测试集群中创建索引库

配置kibana,再重启

PUT /lagou
{
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 1
    }
}
  • number_of_shards:分片数量,这里设置为3
  • number_of_replicas:副本数量,这里设置为1,每个分片一个备份,一个原始数据,共2份。

通过chrome浏览器的head查看,我们可以查看到分片的存储结构:

image.png

可以看到,lagou这个索引库,有三个分片,分别是0、1、2,每个分片有1个副本,共6份。

  • node-01上保存了1号分片和2号分片的副本
  • node-02上保存了0号分片和2号分片的副本
  • node-03上保存了0号分片和1号分片的副本

集群工作原理

shad与replica机制

  1. 一个index包含多个shard,也就是一个index存在多个服务器上
  2. 每个shard都是一个最小工作单元,承载部分数据,比如有三台服务器,现在有三条数据,这三条数据在三台服务器上各方一条
  3. 增减节点时,shard会自动在nodes中负载均衡
  4. primary shard(主分片)和replica shard(副本分片),每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
  5. replica shard是primary shard的副本,负责容错,以及承担读请求负载
  6. primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
  7. primary shard的默认数量是5,replica默认是1(每个主分片一个副本分片),默认有10个shard,5个primary shard,5个replica shard
  8. primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上

集群写入数据

  1. 客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)
  2. coordinating node,对document进行路由,将请求转发给对应的node。(根据一定的算法选择对应的节点进行存储)
  3. 实际上的node上的primary shard处理请求,将数据保存在本地,然后将数据同步到replica node
  4. coordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端

这个路由简单的说就是取模算法,比如说现在有3台服务器,这个时候传过来的id是5,那么5%3=2,就放在第2台服务器

ES查询数据

倒排序算法

查询有个算法叫倒排序:简单的说就是通过分词把词语出现的id进行记录下来,再查询的时候先去查到哪些id包含这个数据,然后再根据id把数据查出来

查询过程

  1. 客户端发送一个请求给coordinate node
  2. 协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard
  3. query phase(查询阶段):每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果
  4. fetch phase(获取阶段),接着由协调节点,根据唯一标识去各个节点进行拉取数据,最终返回给客户端