摘自designing the perfect elasticsearch cluster

本文包含了设计elasticsearch cluster需要了解的方方面面,本文不会告诉你如何设计一个完美的es集群。

  • elasticsearch是一个搜索引擎,不是数据库,不会替代mysql

  • elasticsearch是一个弹性搜索引擎,弹性体现在水平扩展、索引分片;elastic将索引拆分成多个分片存储在不同的host上,分片数量默认为5,需要根据实际workload调整以达到最优性能

  • 高可用设计

elasticsearch集群包含一下4种节点类型:
master nodes: 主节点
data node: 数据节点
http node: 查询节点
coordinating node: 协作节点

最小高可用集群设计:
1. 3数据中心
2. 3主节点,奇数个主节点防止脑裂,将3个主机点分散在各个数据中心
3. 2查询节点,在主节点数据中心各一个
4. 任意数量的数据节点

ES的分片分配算法允许分片分配在不同区域内,根据rack配置将主分片、备份分片分配在不同的区域中
cluster.routing.allocation.awareness.attributes: "rack_id"
node.attr.rack_id: "dontsmokecrack"
  • 理解luence: elasticsearch使用了luence库
1. 每个elasticsearch分片是一个luence索引,一个luence索引最大可包含2,147,483,519条记录。

2. luence将索引划分为多个段,luence顺序搜索这些段;当新写请求来时会创建段,写提交或关闭时,
段即不可变,有新记录添加到elasticsearch index时,luence会创建新的段,luence会不断的将小的段
合并成大的段。luence搜索段是串行的,所以段越多延迟越大。当luence合并时会占用CPU与I/O进而降
低index速度。

3. 当更新或删除文档时luence执行copy on write操作,删除只将文档标记为已删除,索引磁盘占用会
一直增长,除非整个索引删除。

4. luence执行merge时,会将两个段合并成一个新的段后再删除旧的段,merge要确保磁盘空间足够
  • 硬件
CPU: 复杂查询

ElasticSearch主要通过thread_pools使用CPU资源,主要的thread_pool有generic、index、get、bulk、
search等,可用通过GET _nodes/thread_pool?pretty查看当前集群各个节点的thread_pool情况;
thread_pool的线程数、队列数可以通过配置设置,默认不会超过32;当队列满时请求会被ES拒绝,可以
适当调整queue的数值。

Memory:

ElasticSearch作为Java应用程序,内存分配与回收非常关键;ES使用CMS作为默认的垃圾收集器,而CMS
的最大问题是会导致JVM停止,在堆内存大于4G不推荐;Java8推出了新的垃圾收集器G1,专门针对堆大于
4G的情况,G1GC将堆划分为1-32M的区,然后利用后台线程先扫描含垃圾最多的区,不会造成stop the world
的情况;另外由于指针大小的原因不要将堆设置超过31G;禁止swap。
-XX:+UseG1GC -XX:MaxGCPauseMillis=400

Network:

带宽越大越好;可以增加mtu值,以减少网络延时

Storage

存储往往是ES的瓶颈;尽量不要使用机械磁盘,SSD是最好的选择。
在对数据完整性要求不高时,raid0是最佳选择;裸磁盘成本低,故障只会丢失一块盘的数据,但读写速率低;raid10成本高。
  • Software
kernel: 4.9.x
JVM: 8
FS: EXT4,但节点数据大于1TB XFS更佳
  • 索引设计
1. 分片
索引一旦创建,分片数量即不可改变,除非通过reindex;然而在一开始很难确定索引数据量的大小,应该设置多少分片。
< 300万documents    1分片
300万之间500万      2分片
> 500万             int (总数/5000000 +1)
2. 备份
可用利用elasticsearch zones来优化数据备份,将数据分布在不同的机柜