脑裂问题,就是同一个集群中的不同节点对于集群的状态有了不一样的理解,脑裂问题是分布式集群环境中必然会遇到的问题。
那么,来看一个有两个节点的Elasticsearch集群的简单情况。集群维护一个单个索引并有一个分片和一个副本。节点1在启动时被选举为主节点并保存主分片(0P),而节点2保存复制分片(0R)。
假设现在由于网络问题或其他原因,两个节点之间的通信发送中断,这两个节点都认为对方挂掉了,节点1不需要做什么,因为它本身就是主节点,但是节点2会自动选举它自己为主节点,因为节点2和集群的主节点之间已经无法通信。
现在集群处于不一致的状态,发送到节点1上的索引请求不会将数据分配到节点2,同时发送的节点2的请求也不会将数据分配到节点1。在这种情况下,分片的两份数据分开了。如果一个对集群无感知的索引客户端(例如使用REST接口),这个问题非常透明难以发现,请求仍然会成功完成。问题只有在搜索数据时才被隐约发现:取决于搜索请求命中了哪个节点,结果会不同。
要避免脑裂的发生,可以在Elasticsearch的配置文件(config目录中的elasticsearch.yml)中做一些配置。discovery.zen.minimum_master_nodes,这个参数决定了主节点选择过程中最少需要多少个master节点,默认配置是1。一个基本原则是需要设置成N/2+1,N是集群中节点的数量。例如一个3节点集群,minimum_master_nodes应该被设为2。
另一个参数是discovery.zen.ping.timeout,它的默认值是3秒,它用来决定节点之间网络通信的等待时间。如果网络环境较差,可以调大一点。
2节点集群中把minimum_master_nodes参数设为2可以避免脑裂,但是这种情况下一个节点挂了,整个集群就都挂了。所以建议配置3节点集群,设置minimum_master_nodes为2,可以减少脑裂的可能性并保持高可用的优点,即使一个节点失效,但集群还可以正常运行。