前言
ElastiSearch天生就是 分布式的 ,它知道如何通过管理多节点来提高扩容性和可用性。
集群
一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。
当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。
主节点(Master Node)
主节点负责创建索引、删除索引、分配分片、追踪集群中的节点状态等工作。Elasticsearch 中的主节点的工作量相对较轻。
用户的请求可以发往任何一个节点,并由该节点负责分发请求、收集结果等操作,而并不需要经过主节点转发。
数据节点
数据节点,负责数据的存储和相关具体操作,比如索引数据的创建、修改、删除、搜索、聚合。
候选节点
在 Elasticsearch 集群中只有候选节点才有选举权和被选举权。其他节点是不参与选举工作的。
协调节点
是一种角色,而不是真实的 Elasticsearch 的节点,我们没有办法通过配置项来配置哪个节点为协调节点。集群中的任何节点都可以充当协调节点的角色。
当一个节点 A 收到用户的查询请求后,会把查询语句分发到其他的节点,然后合并各个节点返回的查询结果,最好返回一个完整的数据集给用户。
其实任何一个节点都可以完成这样的工作,单独增加这样的节点更多地是为了提高并发性。
数据分片
Elasticsearch 会对索引数据进行切分,同时每一个分片会保存多个副本,其原因和 HDFS 是一样的,都是为了保证分布式环境下的高可用。
当一个节点因为网络或者其他原因宕机,其上的主分片和副本分片会丢失。
副本分片的丢失不会影响数据的读取,主分片的丢失则会有消息丢失的风险,此时需要从其他节点的主分片的副本分片选举一个作为主节点。
主分片和副本分片
一个分片可以是 主 分片或者 副本 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。
副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。设及到数据的增减和修改在主分片上处理过后会转发给副本分篇
数据分布
Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?这个过程是根据下面这个公式决定的:
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
所以我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。
集群健康
集群的状态有 Green、Yellow 和 Red 三种,如下所述:
Green:绿色,健康。所有的主分片和副本分片都可正常工作,集群 100% 健康。
Yellow:黄色,预警。所有的主分片都可以正常工作,但至少有一个副本分片是不能正常工作的。此时集群可以正常工作,但是集群的高可用性在某种程度上被弱化。
Red:红色,集群不可正常使用。集群中至少有一个分片的主分片及它的全部副本分片都不可正常工作。
3C和脑裂
共识性
共识性是分布式系统中最基础也最主要的一个组件,在分布式系统中的所有节点必须对给定的数据或者节点的状态达成共识。
但是 Elasticsearch 并没有使用它们,而是自己实现共识系统 zen discovery。
zen discovery 是 Elasticsearch 的一个核心的基础组件,zen discovery 不仅能够实现共识系统的选择工作,还能够很方便地监控集群的读写状态是否健康。当然,我们也不保证其后期会使用 Zookeeper 代替现在的 zen discovery”。
zen discovery 模块以 “八卦传播”(Gossip)的形式实现了单播(Unicat):单播不同于多播(Multicast)和广播(Broadcast)。节点间的通信方式是一对一的。
并发
Elasticsearch 是一个分布式系统。写请求在发送到主分片时,同时会以并行的形式发送到备份分片,但是这些请求的送达时间可能是无序的。
在这种情况下,Elasticsearch 用乐观并发控制(Optimistic Concurrency Control)来保证新版本的数据不会被旧版本的数据覆盖。
乐观并发控制是一种乐观锁,另一种常用的乐观锁即多版本并发控制(Multi-Version Concurrency Control)。
它们的主要区别如下:
- 乐观并发控制(OCC):是一种用来解决写 - 写冲突的无锁并发控制,认为事务间的竞争不激烈时,就先进行修改,在提交事务前检查数据有没有变化,如果没有就提交,如果有就放弃并重试。乐观并发控制类似于自选锁,适用于低数据竞争且写冲突比较少的环境。
- 多版本并发控制(MVCC):是一种用来解决读 - 写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每一个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。
一致性(Consistency)
Elasticsearch 集群保证写一致性的方式是在写入前先检查有多少个分片可供写入,如果达到写入条件,则进行写操作,否则,Elasticsearch 会等待更多的分片出现,默认为一分钟。
有如下三种设置来判断是否允许写操作:
One:只要主分片可用,就可以进行写操作。
All:只有当主分片和所有副本都可用时,才允许写操作。
Quorum(k-wu-wo/reng,法定人数):是 Elasticsearch 的默认选项。当有大部分的分片可用时才允许写操作。其中,对 “大部分” 的计算公式为 int ((primary+number_of_replicas)/2)+1。
Elasticsearch 集群保证读写一致性的方式是,为了保证搜索请求的返回结果是最新版本的文档,备份可以被设置为 Sync(默认值),写操作在主分片和备份分片同时完成后才会返回写请求的结果。
这样,无论搜索请求至哪个分片都会返回最新的文档。但是如果我们的应用对写要求很高,就可以通过设置 replication=async 来提升写的效率,如果设置 replication=async,则只要主分片的写完成,就会返回写成功。
脑裂
在 Elasticsearch 集群中主节点通过 Ping 命令来检查集群中的其他节点是否处于可用状态,同时非主节点也会通过 Ping 来检查主节点是否处于可用状态。
当集群网络不稳定时,有可能会发生一个节点 Ping 不通 Master 节点,则会认为 Master 节点发生了故障,然后重新选出一个 Master 节点,这就会导致在一个集群内出现多个 Master 节点。
当在一个集群中有多个 Master 节点时,就有可能会导致数据丢失。我们称这种现象为脑裂。