「这是我参与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次,分别改名
第二步:修改每一个节点的配置文件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查看,我们可以查看到分片的存储结构:
可以看到,lagou这个索引库,有三个分片,分别是0、1、2,每个分片有1个副本,共6份。
- node-01上保存了1号分片和2号分片的副本
- node-02上保存了0号分片和2号分片的副本
- node-03上保存了0号分片和1号分片的副本
集群工作原理
shad与replica机制
- 一个index包含多个shard,也就是一个index存在多个服务器上
- 每个shard都是一个最小工作单元,承载部分数据,比如有三台服务器,现在有三条数据,这三条数据在三台服务器上各方一条
- 增减节点时,shard会自动在nodes中负载均衡
- primary shard(主分片)和replica shard(副本分片),每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
- replica shard是primary shard的副本,负责容错,以及承担读请求负载
- primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
- primary shard的默认数量是5,replica默认是1(每个主分片一个副本分片),默认有10个shard,5个primary shard,5个replica shard
- primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上
集群写入数据
- 客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)
- coordinating node,对document进行路由,将请求转发给对应的node。(根据一定的算法选择对应的节点进行存储)
- 实际上的node上的primary shard处理请求,将数据保存在本地,然后将数据同步到replica node
- coordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端
这个路由简单的说就是取模算法,比如说现在有3台服务器,这个时候传过来的id是5,那么5%3=2,就放在第2台服务器
ES查询数据
倒排序算法
查询有个算法叫倒排序:简单的说就是通过分词把词语出现的id进行记录下来,再查询的时候先去查到哪些id包含这个数据,然后再根据id把数据查出来
查询过程
- 客户端发送一个请求给coordinate node
- 协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard
- query phase(查询阶段):每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果
- fetch phase(获取阶段),接着由协调节点,根据唯一标识去各个节点进行拉取数据,最终返回给客户端