Elastic-Search 整理(二):高级篇
ES高级篇
集群部署
集群的意思:就是将多个节点归为一体罢了,这个整体就有一个指定的名字了
window中部署集群 - 了解
把下载好的window版的ES中的data文件夹、logs文件夹下的所有的文件删掉,然后拷贝成三份,对文件重命名

1、修改node-1001节点的config/elasticsearch.yml配置文件。这个配置文件里面有原生的配置信息,感兴趣的可以查看,因为现在要做的配置信息都在原生的配置信息里,只是被注释掉了而已,当然:没兴趣的,直接全选删掉,然后做如下配置
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 集群名称 注意:是把多个节点归为一个整体,所以这个集群名字就是各节点归为一体之后的名字
# 因此:各个节点中这个集群名字也就要一样了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 节点名称 在一个集群中,这个名字要全局唯一
node.name: node-1001
# 是否有资格成为主机节点
node.master: true
# 是否是数据节点
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 当前节点的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 当前节点的端口号
http.port: 1001
# 当前节点的通讯端口( 监听端口 )
transport.tcp.port: 9301
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
2、修改node-1002节点的config/elasticsearch.yml配置文件
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 集群名称 注意:是把多个节点归为一个整体,所以这个集群名字就是各节点归为一体之后的名字
# 因此:各个节点中这个集群名字也就要一样了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 节点名称 在一个集群中,这个名字要全局唯一
node.name: node-1002
# 是否是主机节点
node.master: true
# 是否是数据节点
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 当前节点的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 当前节点的端口号
http.port: 1002
# 当前节点的通讯端口( 监听端口 )
transport.tcp.port: 9302
# 当前节点不知道集群中另外节点是哪些,所以配置,让当前节点能够找到其他节点
discovery.seed_hosts: ["127.0.0.1:9301"]
# ping请求调用超时时间,但同时也是选主节点的delay time 延迟时间
discovery.zen.fd.ping_timeout: 1m
# 重试次数,防止GC[ 垃圾回收 ]节点不响应被剔除
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
3、修改node-1003节点的config/elasticsearch.yml配置文件
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 集群名称 注意:是把多个节点归为一个整体,所以这个集群名字就是各节点归为一体之后的名字
# 因此:各个节点中这个集群名字也就要一样了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 节点名称 在一个集群中,这个名字要全局唯一
node.name: node-1003
# 是否是主机节点
node.master: true
# 是否是数据节点
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 当前节点的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 当前节点的端口号
http.port: 1003
# 当前节点的通讯端口( 监听端口 )
transport.tcp.port: 9303
# 当前节点不知道集群中另外节点是哪些,所以配置,让当前节点能够找到其他节点
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302"]
# ping请求调用超时时间,但同时也是选主节点的delay time
discovery.zen.fd.ping_timeout: 1m
# 重试次数,防止GC[ 垃圾回收 ]节点不响应被剔除
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
依次启动1、2、3节点的bin/elasticsearch.bat即可启动集群
用postman测试集群
GET http://localhost:1001/_cluster/health
// 响应内容
{
"cluster_name": "es-colony",
"status": "green", // 重点查看位置 状态颜色
"timed_out": false,
"number_of_nodes": 3, // 重点查看位置 集群中的节点数量
"number_of_data_nodes": 3, // 重点查看位置 集群中的数据节点数量
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100.0
}
status字段颜色表示:当前集群在总体上是否工作正常。它的三种颜色含义如下:
- green: 所有的主分片和副本分片都正常运行
- yellow: 所有的主分片都正常运行,但不是所有的副本分片都正常运行
- red: 有主分片没能正常运行
附加内容:一些配置说明,下面的一些配置目前有些人可能并没有遇到,但是在这里留个印象吧,知道个大概和怎么去找就行了
官网地址: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules.html
主节点 [ host区域 ] 和 数据节点 [ stale区域 ]:
cluster.name: elastics # 定义集群名称所有节点统一配置
node.name: es-0 # 节点名称自定义
node.master: true # 主节点,数据节点设置为 false
node.data: false # 数据节点设置为true
path.data: /home/es/data # 存储目录,可配置多个磁盘
path.logs: /home/es/logs # 日志文件路径
bootstrap.mlockall: true # 启动时锁定内存
network.publish_host: es-0 # 绑定网卡
network.bind_host: es-0 # 绑定网卡
http.port: 9200 # http端口
discovery.zen.ping.multicast.enabled: false # 禁用多播,跨网段不能用多播
discovery.zen.ping_timeout: 120s
discovery.zen.minimum_master_nodes: 2 # 至少要发现集群可做master的节点数,
client.transport.ping_timeout: 60s
discovery.zen.ping.unicast.hosts: ["es-0","es-1", "es-2","es-7","es-8","es-4","es-5","es-6"] # 集群自动发现
# fd 是 fault detection
# discovery.zen.ping_timeout 仅在加入或者选举 master 主节点的时候才起作用;
# discovery.zen.fd.ping_timeout 在稳定运行的集群中,master检测所有节点,以及节点检测 master是否畅通时长期有用
discovery.zen.fd.ping_timeout: 120s # 超时时间(根据实际情况调整)
discovery.zen.fd.ping_retries: 6 # 重试次数,防止GC[垃圾回收]节点不响应被剔除
discovery.zen.fd.ping_interval: 30s # 运行间隔
# 控制磁盘使用的低水位。默认为85%,意味着如果节点磁盘使用超过85%,则ES不允许在分配新的分片。当配置具体的大小如100MB时,表示如果磁盘空间小于100MB不允许分配分片
cluster.routing.allocation.disk.watermark.low: 100GB # 磁盘限额
# 控制磁盘使用的高水位。默认为90%,意味着如果磁盘空间使用高于90%时,ES将尝试分配分片到其他节点。上述两个配置可以使用API动态更新,ES每隔30s获取一次磁盘的使用信息,该值可以通过cluster.info.update.interval来设置
cluster.routing.allocation.disk.watermark.high: 50GB # 磁盘最低限额
node.zone: hot # 磁盘区域,分为hot和stale,做冷热分离
script.inline: true # 支持脚本
script.indexed: true
cluster.routing.allocation.same_shard.host: true # 一台机器部署多个节点时防止一个分配到一台机器上,宕机导致丢失数据
# 以下6行为设置thread_pool
threadpool.bulk.type: fixed
threadpool.bulk.size: 32
threadpool.bulk.queue_size: 100
threadpool.search.type: fixed
threadpool.search.size: 49
threadpool.search.queue_size: 10000
script.engine.groovy.inline.aggs: on
# 以下为配置慢查询和慢索引的时间
index.search.slowlog.threshold.query.warn: 20s
index.search.slowlog.threshold.query.info: 10s
index.search.slowlog.threshold.query.debug: 4s
index.search.slowlog.threshold.query.trace: 1s
index.search.slowlog.threshold.fetch.warn: 2s
index.search.slowlog.threshold.fetch.info: 1600ms
index.search.slowlog.threshold.fetch.debug: 500ms
index.search.slowlog.threshold.fetch.trace: 200ms
index.indexing.slowlog.threshold.index.warn: 20s
index.indexing.slowlog.threshold.index.info: 10s
index.indexing.slowlog.threshold.index.debug: 4s
index.indexing.slowlog.threshold.index.trace: 1s
# 索引库设置
indices.fielddata.cache.size: 20% # 索引库缓存时占用大小
indices.fielddata.cache.expire: "48h" # 索引库缓存的有效期
indices.cache.filter.size: 10% # 索引库缓存过滤占用大小
index.search.slowlog.level: WARN # 索引库搜索慢日志级别
Linux中部署ES
部署单机ES
1、准备工作
- 下载linux版的ES,自行百度进行下载,老规矩,我的版本是:7.8.0
- 将下载好的linux版ES放到自己的服务器中去
2、解压文件:
# 命令
tar -zxvf elasticsearch-7.8.0-linux-x86_64.tar.gz
3、对文件重命名:
# 命令
mv elasticsearch-7.8.0 es
4、创建用户:因为安全问题, Elasticsearch 不允许 root 用户直接运行,所以要创建新用户,在 root 用户中创建新用户
useradd es # 新增 es 用户
passwd es # 为 es 用户设置密码,输入此命令后,输入自己想设置的ES密码即可
userdel -r es # 如果错了,可以把用户删除了再重新加
chown -R es:es /opt/install/es # 文件授权 注意:/opt/install/es 改成自己的ES存放路径即可
5、修改 config/elasticsearch.yml 配置文件
# 在elasticsearch.yml文件末尾加入如下配置
cluster.name: elasticsearch
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1"]
6、修改 /etc/security/limits.conf 文件
# 命令
vim /etc/security/limits.conf
# 在文件末尾中增加下面内容 这个配置是:每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
7、修改 /etc/security/limits.d/20-nproc.conf 文件
# 命令
vim /etc/security/limits.d/20-nproc.conf
# 在文件末尾中增加下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
# 操作系统级别对每个用户创建的进程数的限制
* hard nproc 4096
# 注: * 表示 Linux 所有用户名称
8、修改 /etc/sysctl.conf 文件
# 在文件中增加下面内容
# 一个进程可以拥有的 VMA(虚拟内存区域)的数量,默认值为 65536
vm.max_map_count=655360
9、重新加载文件
# 命令
sysctl -p
10、启动程序 : 准备进入坑中
cd /opt/install/es/
# 启动
bin/elasticsearch
# 后台启动
bin/elasticsearch -d

这个错误告知:不能用root用户,所以:切换到刚刚创建的es用户
# 命令
su es
然后再次启动程序,进入下一个坑

这个错误是因为:启动程序的时候会动态生成一些文件,这和ES没得关系,所以:需要切回到root用户,然后把文件权限再次刷新一下
# 切换到root用户
su root
# 切换到root用户之后,执行此命令即可
chown -R es:es /opt/install/es
# 再切换到es用户
su es

11、再次启动程序

吃鸡,这样linux中单机ES就部署成功了
不过啊,前面这种方式都是low的方式,有更简单的方式,就是使用docker容器来进行配置,简直不要太简单,虽然:使用docker容器来启动程序有弊端,如:MySQL就不建议放在docker容器中,因为:MySQL是不断地进行io操作,放到docker容器中,就会让io操作效率降低,而ES放到docker中也是同样的道理,但是:可以玩,因为:有些公司其实并没有在意docker的弊端,管他三七二十一扔到docker中
如果想要用docker容器进行ES配置,编写如下的docker-compose.yml文件
version: "3.1"
services:
elasticsearch:
# 注:此网站版本不全,可以直接用官网 elasticsearch:7.8.0
image: daocloud.io/library/elasticsearch:7.9.0
restart: always
container_name: elasticsearch
ports:
- 9200:9200
environment:
- Java_OPTS=--Xms256m -Xmx1024m
然后启动容器即可
注:使用docker安装需要保证自己的linux中安装了docker和docker-compose, 没有安装的话,教程链接:centos7安装docker和docker-compose
注:有些人可能还会被防火墙整一下,贫道的防火墙是关了的
# 暂时关闭防火墙
systemctl stop firewalld
# 永久关闭防火墙
systemctl enable firewalld.service # 打开防火墙永久性生效,重启后不会复原
systemctl disable firewalld.service # 关闭防火墙,永久性生效,重启后不会复原
12、测试是否成功
// 在浏览器或postman中输入以下指令均可
GET http://ip:9200/

浏览器访问不了,看看自己服务器开放9200端口没有,别搞这种扯犊子事啊
部署集群ES
可以选择和windows版的集群搭建一样
- 解压ES、重命名
- 复制几份ES文件夹
- 修改对应配置
更简单的方式
- 解压linux版的ES,重命名
- 分发节点
# 分发节点的步骤
xsync es-cluster # es-cluster为解压之后的es名字
# 注:xsync需要单独配置,配置过程如下:
# 1、安装rsync
yum -y install rsync
# 配置hosts 节点服务配置 此配置是在/etc/hosts中进行的
ip name # 如:192.168.0.100 hadoop
# 2、编写脚本 看自己的/usr/local/bin中是否有xsync文件 都看这里了,那就是第一次弄,肯定没有,所以
# 在/usr/local/bin中新建一个xsync文件 touch xsync
# 编辑内容如下:
#!/bin/sh
# 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if((pcount==0)); then
echo no args...;
exit;
fi
# 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname
# 获取上级目录的绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir
# 获取当前用户名称
user=`whoami`
# 循环
for((host=1; host<=2; host++)); do
echo $pdir/$fname $user@slave$host:$pdir
echo ==================slave$host==================
rsync -rvl $pdir/$fname $user@slave$host:$pdir
done
# Note:这里的slave对应自己主机名,需要做相应修改。另外,for循环中的host的边界值由自己的主机编号决定
# 3、给新建的xsync文件授权
chmod a+x xsync
# 这样就配置成功了
1、同样的,root用户不能直接运行,所以创建用户
useradd es # 新增 es 用户
passwd es # 为 es 用户设置密码
userdel -r es # 如果错了,可以删除再加
chown -R es:es /opt/module/es # 给文件夹授权
2、编辑 ES文件夹的config/elasticsearch.yml文件,实现集群配置
# 加入如下配置,这些配置在网上都有,看不懂的网上比我更详细
# 集群名称
cluster.name: cluster-es
# 节点名称, 每个节点的名称不能重复
node.name: node-1
# ip 地址, 每个节点的地址不能重复
network.host: zixieqing-linux1 # 这个主机名字是在前面使用xsync异步分发时在hosts中配置的名字
# 是不是有资格主节点
node.master: true
node.data: true
http.port: 9200
# head 插件需要这打开这两个配置
http.cors.allow-origin: "*"
http.cors.enabled: true
http.max_content_length: 200mb
# es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举 master
cluster.initial_master_nodes: ["node-1"]
# es7.x 之后新增的配置,节点发现
discovery.seed_hosts: ["zixieqing-linux1:9300","zixieqing-linux2:9300","zixieqing-linux3:9300"]
gateway.recover_after_nodes: 2
network.tcp.keep_alive: true
network.tcp.no_delay: true
transport.tcp.compress: true
# 集群内同时启动的数据任务个数,默认是 2 个
cluster.routing.allocation.cluster_concurrent_rebalance: 16
# 添加或删除节点及负载均衡时并发恢复的线程个数,默认 4 个
cluster.routing.allocation.node_concurrent_recoveries: 16
# 初始化数据恢复时,并发恢复线程的个数,默认 4 个
cluster.routing.allocation.node_initial_primaries_recoveries: 16
3、修改 etc/security/limits.conf
# 在文件末尾中增加下面内容
es soft nofile 65536
es hard nofile 65536
4、修改 /etc/security/limits.d/20-nproc.conf
# 在文件末尾中增加下面内容
es soft nofile 65536
es hard nofile 65536
* hard nproc 4096
# 注: * 表示 Linux 所有用户名称
5、修改/etc/sysctl.conf
# 在文件中增加下面内容
vm.max_map_count=655360
6、加载文件
sysctl -p
7、启动软件
cd /opt/module/es-cluster
# 启动
bin/elasticsearch
# 后台启动
bin/elasticsearch -d
防火墙的问题前面已经提到了
8、集群验证

分片、副本、分配
分片 shards - 重要
这玩意儿就类似于关系型中的分表
在关系型中如果一个表的数据太大了,查询效率很低、响应很慢,所以就会采用大表拆小表,如:用户表,不可能和用户相关的啥子东西都放在一张表吧,这不是找事吗?因此:需要分表
相应的在ES中,也需要像上面这么干,如:存储100亿文档数据的索引,在单节点中没办法存储这么多的文档数据,所以需要进行切割,就是将这整个100亿文档数据切几刀,然后每一刀切分出来的每份数据就是一个分片 ( 索引 ),然后在切开的每份数据单独放在一个节点中,这样切开的所有文档数据合在一起就是一份完整的100亿数据,因此:这个的作用也是为了提高效率
创建一个索引的时候,可以指定想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上
分片有两方面的原因:
- 允许水平分割 / 扩展内容容量,水平扩充,负载均衡嘛
- 允许在分片之上进行分布式的、并行的操作,进而提高性能 / 吞吐量
注意: 当 Elasticsearch 在索引中搜索的时候, 它发送查询到每一个属于索引的分片,然后合并每个分片的结果到一个全局的结果集中
副本 Replicas - 重要
这不是游戏中的刷副本的那个副本啊。是指:分片的复制品
失败是常有的事嘛,所以:在ES中也会失败呀,可能因为网络、也可能因此其他鬼原因就导致失败了,此时不就需要一种故障转移机制吗,也就是 创建分片的一份或多份拷贝,这些拷贝就叫做复制分片( 副本 )
副本( 复制分片 )之所以重要,有两个原因:
- 在分片 / 节点失败的情况下,提供了高可用性。因为这个原因,复制分片不与原 / 主要( original / primary )分片置于同一节点上是非常重要的
- 扩展搜索量 / 吞吐量,因为搜索可以在所有的副本上并行运行
多说一嘴啊,分片和副本这两个不就是配套了吗,分片是切割数据,放在不同的节点中( 服务中 );副本是以防服务宕掉了,从而丢失数据,进而把分片拷贝了任意份。这个像什么?不就是主备吗( 我说的是主备,不是主从啊 ,这两个有区别的,主从是主机具有写操作,从机具有读操作;而主备是主机具有读写操作,而备机只有读操作 ,不一样的啊 )
有个细节需要注意,在ES中,分片和副本不是在同一台服务器中,是分开的,如:分片P1在节点1中,那么副本R1就不能在节点1中,而是其他服务中,不然服务宕掉了,那数据不就全丢了吗
分配 Allocation
前面讲到了分片和副本,对照Redis中的主备来看了,那么对照Redis的主从来看呢?主机宕掉了怎么重新选一个主机?Redis中是加了一个哨兵模式,从而达到的。那么在ES中哪个是主节点、哪个是从节点、分片怎么去分的?就是利用了分配
所谓的分配是指: 将分片分配给某个节点的过程,包括分配主分片或者副本。如果是副本,还包含从主分片复制数据的过程。注意:这个过程是由 master 节点完成的,和Redis还是有点不一样的啊
既然都说了这么多,那就再来一个ES的系统架构吧

其中,P表示分片、R表示副本
默认情况下,分片和副本都是1,根据需要可以改变
单节点集群
这里为了方便就使用window版做演示,就不再linux中演示了
1、打开前面玩的window版集群的1节点

2、创建索引 把这个索引切成3份( 切片 )、每份拷贝1份副本
PUT http://127.0.0.1:1001/users
// 请求体内容
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
3、开始安装head插件,这就是一个可视化界面而已,后续还会用Kibana
还有一种es的集群监控的方式是使用cerebro,官网地址:https://github.com/lmenezes/cerebro 下载解压,运行 bin/cerebro.bat 即可
自行到官网下载elasticsearch-head-master,这是用Vue写的。启动效果如下:

访问上图中的地址即可,但是:这个端口是9100,而我们的ES是9200端口,所以9100访问9200是跨越的,因此:需要对ES设置跨越问题,而这个问题在第一次玩ES集群时就配置了的

head打开之后就是下图中的样子

head链接ES之后就是下图的样子

三种颜色再巩固一下:
- green:所有的主分片和副本分片都正常运行
- yellow:所有的主分片都正常运行,但不是所有的副本分片都正常运行
- red:有主分片没能正常运行
但是:上述的单节点集群有问题,就是将分片和副本都放在一个节点( node-1001 )中了,这样会导致前面说的服务宕掉,数据就没了,做的副本就是无用功。要解决就要引入接下来的内容了
故障转移
所谓的故障转移指的就是:
- 若新开节点,那么ES就会将原有数据重新分配到所有节点上
- 若是节点挂了,那么ES就会将挂了的节点的数据进行拷贝到另外好的节点中。要是挂的正好是master主节点,那么还有多一个选主过程,然后再分配数据————这种情况也可以称之为“应对故障”
1、新开节点的情况: 启动node-1002节点
可能由于玩windows版时的一些数据导致node-1002节点启动不了,所以删掉data文件夹和logs文件夹下的东西即可
刷新head可视化页面:

恢复正常
水平扩容 / 负载均衡
1、启动node-1003节点

刷新head页面

对照前面单节点集群来看,数据就被很好的分开了,这样性能不就提上来了吗
但是:如果相应继续扩容呢?即:超过6份数据( 6个节点,前面讲到过索引切分之后,每一份又是单独的索引、副本也算节点 ),那怎么办?
- 首先知道一个点:主分片的数目在索引创建时就已经确定下来了的,这个我们没法改变,这个数目定义了这个索引能够存储的最大数据量( 实际大小取决于你的数据、硬件和使用场景 )
- 但是,读操作——搜索和返回数据——可以同时被主分片 或 副本分片所处理,所以当你拥有越多的副本分片时,也将拥有越高的吞吐量
- 因此:增加副本分片的数量即可
put http://127.0.0.1:1001/users/_settings
// 请求体内容
{
"number_of_replicas": 2
}
刷新head页面

应对故障
应对的是什么故障?前面一直在说:服务宕掉了嘛
1、关掉node-1001节点( 主节点 )
2、刷新head页面

但是注意啊:yellow虽然不正常,但是不影响操作啊,就像你看了yellow之后,影响你正常发挥吗?只是可能有点虚脱而已,所以对于ES来说也是可以正常查询数据的,只是:效率降低了而已嘛( 主节点和3个分片都在的嘛 )
3、解决这种问题: 开启新节点(把node-1001节点启动。此时它就不是主节点了 ,当成新节点了)

这就会报错: unless existing master is discovered 找不到主节点( 对于启动的集群来说,它现在是新节点],因此:需要做一下配置修改( node-1001的 config/ElasticSearch.yml )
discovery.seed_hosts: ["127.0.0.1:9302","127.0.0.1:9303"]
保存开启node-1001节点即可
4、刷新head页面

故障恢复了,所以:这也告知一个问题,配置集群时,最好在每个节点的配置文件中都加上上述的配置,从而节点宕掉之后,重启节点即可( 不然每次改不得烦死 ),注意:ES版本不一样,这个配置方法不一样的,6.x的版本是用cluster.initial_master_nodes: 来进行配置的
路由计算和分片控制理论
路由计算
路由、路由,这个东西太熟悉了,在Vue中就见过路由router了( 用来转发和重定向的嘛 )
那在ES中的路由计算又是怎么回事?这个主要针对的是ES集群中的存数据,试想:你知道你存的数据是在哪个节点 / 哪个主分片中吗( 副本是拷贝的主分片,所以主分片才是核心 )?
- 当然知道啊,就是那几个节点中的任意一个嘛。娘希匹~这样的骚回答好吗?其实这是由一个公式来决定的
shard = hash( routing ) % number_of_primary_shards
routing 是一个任意值,默认是文档的_id,也可以自定义
number_of_primary_shards 表示主分片的数量,如前面切分为了3份
hash() 是一个hash函数
这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量:因为如果数量变化了,那么之前所有路由的值都会无效,文档也再也找不到了
分片控制
既然有了存数据的问题,那当然就有取数据的问题了。
请问:在ES集群中,取数据时,ES怎么知道去哪个节点中取数据( 假如在3节点中,你去1节点中,可以取到吗?),因此:来了分片控制
负载均衡,轮询嘛。所以这里有个小知识点,就是:协调节点 coordinating node,我们可以发送请求到集群中的任一节点,每个节点都有能力处理任意请求,每个节点都知道集群中任一文档位置,这就是分片控制,而我们发送请求的那个节点就是:协调节点,它会去帮我们找到我们要的数据在哪里
综合前面的知识就可以得到:
-
所谓的分片就是:将索引切分成任意份嘛,然后得到的每一份数据都是一个单独的索引
-
分片完成后,我们存数据时,存到哪个节点上,就是通过 shard = hash( routing ) % number_of_primary_shards 得到的
-
而我们查询数据时,ES怎么知道我们要找的数据在哪个节点上,就是通过协调节点做到的,它会去找到和数据相关的“所有节点”,从而轮询,然后进行数据整合,通过协调节点返回给客户端。因此最后的结果可能是从主分片上得到的,也可能是从副本上得到的,就看最后轮询到的是哪个节点罢了
集群下的数据写流程
新建、删除请求都是写操作, 必须在主分片上面完成之后才能被复制到相关的副本分片
整个流程也很简单
- 客户端请求任意节点(协调节点)
- 通过路由计算,协调节点把请求转向指定的节点
- 转向的节点的主分片保存数据
- 主节点再将数据转发给副本保存
- 副本给主节点反馈保存结果
- 主节点给客户端反馈保存结果
- 客户端收到反馈结果

但是:从图中就可以看出来,这套流程完了,才可以做其他事( 如:才可以去查询数据 ),那我为什么不可以异步呢?就是我只要保证到了哪一个步骤之后,就可以进行数据查询,所以:这里有两个小东西需要了解
在进行写数据时,我们做个小小的配置,这就是接下来的两个小节内容
一致性 consistency
这玩意就是为了和读数据搭配起来嘛,写入和读取保证数据的一致性呗
这玩意儿可以设定的值如下:
- one :只要主分片状态 ok 就允许执行读操作,这种写入速度快,但不能保证读到最新的更改
- all:这是强一致性,必须要主分片和所有副本分片的状态没问题才允许执行写操作
- quorum:这是ES的默认值。即大多数的分片副本状态没问题就允许执行写操作。这是折中的方法,write的时候,W>N/2,即参与写入操作的节点数W,必须超过副本节点数N的一半,在这个默认情况下,ES是怎么判定你的分片数量的,就一个公式:
int((primary + number_of_replicas) / 2) + 1
primary 指的是创建的索引数量
number_of_replicas 是指的在索引设置中设定的副本分片数
如果你的索引设置中指定了当前索引拥有3个副本分片
那规定数量的计算结果为:int(1 primary + 3 replicas) / 2) + 1 = 3,
如果此时你只启动两个节点,那么处于活跃状态的分片副本数量就达不到规定数量,
也因此你将无法索引和删除任何文档
- realtime request:就是从translog里头读,可以保证是最新的。但是注意:get是最新的,但是检索等其他方法不是( 如果需要搜索出来也是最新的,需要refresh,这个会刷新该shard但不是整个index,因此如果read请求分发到repliac shard,那么可能读到的不是最新的数据,这个时候就需要指定preference=_primar y)
超时 timeout
如果没有足够的副本分片会发生什么?Elasticsearch 会等待,希望更多的分片出现。默认情况下,它最多等待 1 分钟。 如果你需要,你可以使用timeout参数使它更早终止,单位是毫秒,如:100就是100毫秒
新索引默认有1个副本分片,这意味着为满足规定数量应该需要两个活动的分片副本。 但是,这些默认的设置会阻止我们在单一节点上做任何事情。为了避免这个问题,要求只有当number_of_replicas 大于1的时候,规定数量才会执行
上面的理论不理解、或者感觉枯燥也没事儿,后面慢慢的就理解了,这里只是打个预防针、了解理论罢了
集群下的数据读流程
有写流程,那肯定也要说一下读流程嘛,其实和写流程很像,只是变了那么一丢丢而已
流程如下:
- 客户端发送请求到任意节点( 协调节点 )
- 这里不同,此时协调节点会做两件事:1、通过路由计算得到分片位置,2、还会把当前查询的数据所在的另外节点也找到( 如:副本 )
- 为了负载均衡( 可能某个节点中的访问量很大嘛,减少一下压力咯 ),所以就会对查出来的所有节点做轮询操作,从而找到想要的数据( 因此:你想要的数据在主节点中有、副本中也有,但是:给你的数据可能是主节点中的,也可能是副本中的 ———— 看轮询到的是哪个节点中的 )
- 节点反馈结果
- 客户端收到反馈结果