Elasticsearch-101-生产集群部署服务器配置等建议

我们之前一直是在windows环境下去启动一个单节点的es进程,如果是在生产环境中,肯定是要部署在linux集群上面了

那么部署es的服务器对配置有什么要求呢

内存

es是很吃内存的,es吃的主要不是你的jvm的内存,一般来说es用jvm heap(堆内存)还是用的比较少的,主要吃的是你的机器的内存

es底层基于lucene,lucene是基于磁盘文件来读写和保存你的索引数据的,比如正排索引 倒排索引这些,lucene的特点就是会基于os filesystem cache,会尽量将频繁访问的磁盘文件的数据在操作系统的内存中进行缓存,然后尽量提升磁盘文件读写的性能

es的性能80%取决于说,你的机器上,除了分配给jvm heap内存以外,还剩下多少内存,剩下的内存会留给es的磁盘索引文件做缓存,如果os cache能够缓存更多的磁盘文件的数据,索引文件的数据,索引读写的性能都会高很多,特别是检索

但是如果你的大量的索引文件在os cache中放不下,还是停留在磁盘上,那么搜索 聚合的时候大量的都是读写磁盘文件,性能就会很低了

如果说在es生产环境中,哪种资源最容易耗尽,那么就是内存了.排序和聚合都会耗费掉很多jvm 堆内存,所以给es进程分配足够的jvm heap内存是很重要的.除了给jvm heap分配内存,还需要给予足够的内存给os filesystem cache.因为lucene用的数据结构都是给予磁盘的格式,es是通过os cache来进行高性能的磁盘文件读写的.

一般而言,除非说你的数据量很小,比如就是一些OA系统,各种信息管理系统,要做一个内部的检索引擎,有几万,几十万,几百万的数据量,对机器的资源配置要求还是蛮低的.一般而言,如果你的数据量过亿,几亿,几十亿.那么其实建议你的每台机器都给64G的内存的量.

如果一个机器有64G的内存,那么是比较理想的状态,但是32GB和16GB的内存也是ok的.具体的内存数量还是根据数据量来决定.但是如果一个机器的内存数量小于8G,那么就不太适合生产环境了,因为我们可能就需要很多小内存的机器来搭建集群.而大于64G的机器也不是很有必要.

CPU

大多数的es集群对于cpu的要求都会比较低一些,因此一台机器有多少个cpu core其实对生产环境的es集群部署相对来说没有那么的重要了,至少没有内存来的重要.当然,肯定是要用多核处理器的,一般来说2个cpu core~8个cpu core都是可以的.

此外,如果说要选择是较少的cpu core但是cpu性能很高,还是较多的cpu core但是cpu性能较为一般,那么肯定是选择性能较为一般但是更多的cpu core.因为更多的cpu core可以提供更强的并发处理能力,远比单个cpu性能高带来的效果更加明显.

磁盘

对于es的生产环境来说,磁盘是非常重要的,尤其是对那些大量写入的es集群,比如互联网公司将每天的实时日志数据以高并发的速度写入es集群.在服务器上,磁盘是最慢的那个资源,所以对于大量写入的es集群来说,会很容易因为磁盘的读写性能造成整个集群的性能瓶颈.

如果我们能够使用SSD固态硬盘,而不是机械硬盘,那么当然是最好的,SSD的性能比机械硬盘可以高很多倍,可以让es的读写性能都高很多倍.所以,如果公司出的起钱大量使用固态硬盘,那么当然是最好的.

如果我们用SSD硬盘的话,那么需要检查我们的I/O scheduler,需要正确的配置IO scheduler.当我们将数据写入磁盘时,IO scheduler会决定什么时候数据才会真正的写入磁盘,而不是停留在os cache内存缓冲中.大多数机器上,默认的IO scheduler是cfq,也就是completely fair queuing.

这个scheduler会给每个进程都分配一些时间分片(time slice), 然后会优化每个进程的数据如何写入磁盘中,优化的思路主要 是根据磁盘的物理布局来决定如何将数据写入磁盘,进而提升写入磁盘的性能.这是针对机械硬盘做出的优化,因为机械硬盘是一种旋转存储介质,是通过机械旋转磁盘+磁头进行磁盘读写的机制.

但是scheduler的这种默认的执行机制,对于SSD来说是不太高效的,因为SSD跟机械硬盘是不一样的,SSD不涉及到机械磁盘旋转和磁头读取这种传统的读写机制.对于SSD来说,应该用deadline/noop scheduler.deadline scheduler会基于写操作被pending了多长时间来进行写磁盘优化,而noop scheduler就是一个简单的FIFO队列先进先出的机制.

调整io scheduler可以带来很大的性能提升,甚至可以达到数百倍.

如果我们没有办法使用SSD,只能使用机械硬盘,那么至少得尽量正确读写速度最快的磁盘,比如高性能的服务器磁盘.

此外,使用RAID 0也是一种提升磁盘读写速度的高效的方式,无论是对于机械硬盘,还是SSD,都一样.RAID 0也被称之为条带式存储机制(striping),,在RAID各种级别中性能是最高的.

RAID 0的基本原理,是把连续的数据分散存储到多个磁盘上进行读写,也就是对数据进行条带式存储.这样系统的磁盘读写请求就可以被分散到多个磁盘上并行执行.但是没有必要使用镜像或者RAID的其他模式,因为我们不需要通过RAID来实现数据高可用存储,es的replica副本机制本身已经实现了数据高可用存储.

最后,我们要避免跟网络相关的存储模式,network-attached storage,NAS,比如基于网络的分布式存储模式.虽然很多供应商都说他们的NAS解决方案性能非常高,而且比本地存储的可靠性更高.但是实际上用起来会有很多性能和可靠性上的风险,一般因为网络传输会造成较高的延时,同时还有单点故障的风险.

网络

对于es这种分布式系统来说,快速而且可靠的网络是非常的重要的.因为高速网络通信可以让es的节点间通信达到低延时的效果,高带宽可以让shard的移动和恢复,以及分配等操作更加的快速.现代的数据中心的网络对于大多数的集群来说,性能都足够高了.比如千兆网卡,这都是可以的.

但是要避免一个集群横跨多个数据中心,比如异地多机房部署一个集群,因为那样的话跨机房,跨地域的传输会导致网络通信和数据传输性能较差.es集群是一种p2p模式的分布式系统架构,不是master-slave主从分布式系统.在es集群中,所有的node都是相等的,任意两个node间的互相通信都是很频繁和正常的.因此如果部署在异地多机房,那么可能会导致node间频繁跨地域进行通信,通信延时会非常高,甚至造成集群运行频繁不正常.

就跟NAS存储模式一样,很多供应商都说跨地域的多数据中心是非常可靠的,而且低延时的.一般来说,可能的确是这样,但是一旦发生了网络故障,那么集群就完了.通常来说,跨地域多机房部署一个es集群带来的效益,远远低于维护这样的集群所带来的额外成本.

自建集群 vs 云部署

现在一般很容易就可以拿到高性能的机器来部署集群,很多高性能的机器可以有上百G的内存资源,还有几十个cpu core.但是同时我们也可以再云供应商上,比如阿里云,租用大量的小资源的虚拟机.那么对于自己购买昂贵高性能服务器自建集群,以及租用云机器来部署,该选择哪种方案呢?

比如说,你自己购买5台 8核64G的物理机,搭建es集群 或者是上阿里云买了16台2核4G的虚拟机来搭建es集群

一般来说,对于es集群而言,是建议拥有少数机器,但是每个机器的资源都非常多,尽量避免拥有大量的少资源的虚拟机.因为对于运维和管理来说,管理5个物理机组成的es集群,远远比管理100个虚拟机组成的es集群要简单的多.

同时即使是自建集群,也要尽量避免那种超大资源量的超级服务器,因为那样可能造成资源无法完全利用,然后在一个物理机上部署多个es节点,这会导致我们的集群管理更加的复杂.

JVM

对于最新的es版本,一般多建议用最新的jvm版本,除非es明确说明要用哪个jdk版本.es和lucene都是一种满足特殊需求的软件,lucene的单元测试和集成测试中,经常会发现jvm自身的一些bug.这些bug涵盖的范围很广,因此尽量用最新的jvm版本,bug会少一些.

就目前es 5.x版本而言,建议用jdk 8,而不是jdk 7,同时jdk 6已经不再被支持了.

如果我们用java编写es应用程序,而且在使用transport client或者node client,要确保运行我们的应用程序的jvm版本跟es服务器运行的jvm版本是一样的.在es中,有些java的本地序列化机制都被使用了,比如ip地址,异常信息,等等.而jvm可能在不同的minor版本之间修改序列化格式,所以如果client和server的jvm版本不一致,可能有序列化的问题.

同时官方推荐,绝对不要随便调整jvm的设置.虽然jvm有几百个配置选项,而且我们可以手动调优jvm的几乎方方面面.同时遇到一个性能场景的时候,每个人都会第一时间想到去调优jvm,但是es官方还是推荐我们不要随便调节jvm参数.因为es是一个非常复杂的分布式软件系统,而且es的默认jvm配置都是基于真实业务场景中长期的实践得到的.随便调节jvm配置反而有可能导致集群性能变得更加差,以及出现一些未知的问题.反而是很多情况下,将自定义的jvm配置全部删除,性能是保持的最好的.

容量规划

在规划你的es集群的时候,一般要规划你需要多少台服务器,每台服务器要有多少资源,能够支撑你预计的多大的数据量.但是这个东西其实不是一概而论的,要视具体的读写场景,包括你执行多么复杂的操作,读写QPS来决定的.不过一般而言,对于很多的中小型公司,都是建议es集群承载的数据量在10亿规模以内.用最合理的技术做最合理的事情.

比如做网站或者app的搜索引擎,一般数据量会相对来说大一些,但是通常而言,一个网站或者app的内容都是有限的,不会无限膨胀,通常数据量从百万级到亿级不等,因此用于搜索的数据都放在es中是合理的.

然后一些软件系统或者特殊项目的搜索引擎,根据项目情况不同,数据量也是从百万量级到几十亿,甚至几百亿,或者每日增量几亿,都有可能,那么此时就要根据具体的业务场景来决定了.如果数据量特别大,日增量都几亿规模,那么其实建议不要将每天全量的数据都写入es中,es也不适合这种无限规模膨胀的场景.es是很耗费内存的,无限膨胀的数据量,会导致我们无法提供足够的资源来支撑这么大的数据量.可以考虑是不是就将部分热数据,比如最近几天的数据,放到es中做高频高性能搜索,然后将大量的很少访问的冷数据放大数据系统做离线批量处理,比如hadoop系统里面.

同时如果数据量在10亿以内的规模,那么一般而言,如果提供5台以上的机器,每台机器的配置到8核64G的配置,一般而言都能hold住.当然,这个也看具体的使用场景,如果你读写特别频繁,或者查询特别复杂,那么可能还需要更多的机器资源.如果你要承载更大的数据量,那么就相应的提供更多的机器和资源.

要提升你的es的性能,最重要的,还是说规划合理的数据量,物理内存资源大小,os cache