Elasticsearch是一个基于Lucene的搜索服务器。它基于RESTful web接口提供了一个分布式多用户能力的全文搜索引擎。Elasticsearch是用Java语言开发的,是一种目前流行的企业级搜索引擎。
近乎实时搜索、稳定、可靠、快速、安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby、Go和许多其他语言中都是可用的。可以作为一个大型分布式集群(数百台服务器)技术,处理PB级数据,服务大公司;也可以运行在单机上,服务小公司。
以上只列举了部分应用场景,不同场景下Elasticsearch的架构选型及优化思路的侧重点亦不同。
以日志中心系统为例,简单介绍一下针对于该系统曾经做过的架构选型思路以及调优策略。首先,需明确日志中心也有细微区别,大致分为两类:
实时写入及查询场景下,架构选型分析
该场景由于涉及到实时写入,故而写入流量从全天维度来看,集群整体CPU,内存的资源使用情况会保持较高的一个情况,故而在规划时,应对集群各节点进行角色区分,以曾经规划过的集群架构为例:
节点角色 | 角色描述 | 节点数量 | CPU | 内存 | 存储 | 存储介质 |
---|---|---|---|---|---|---|
仲裁节点 | 协调集群选举 | 1 | 2C | 6G | 50G | 对象存储 |
协调节点 | 请求集群的流量处理,网关 | 2 | 24C | 54G | 50G | 对象存储 |
主节点 | 协调技术集群内部资源的分配 | 2 | 24C | 54G | 50G | 对象存储 |
数据节点 | 存储数据 | 8 | 24C | 54G | 2T | 对象存储 |
针对实时写入及查询的场景,在进行架构规划时,设计了两个协调节点的角色,elastic-es-zone-a-coord,elastic-es-zone-b-coord,协调节点相当于是集群的统一网关,发起数据写入请求时,优先通过协调节点进行流量处理,而非直接将请求打到数据节点上,给数据节点较大负载压力。
同样的,查询时,查询请求也会预先经过协调节点进行流量处理,不会直接请求数据节点,数据节点只扮演存储数据以及提供数据的角色。
在此种架构,未做任何集群调优策略的情况下,在面对日增量在10亿级日志数据时,写入速率在每秒10W-12W条数据左右,数据写入无延迟,数据查询也能做到近实时查询,秒级响应。各节点系统资源使用情况如下(此处统计的为日常情况下的均值,仅供参考):
节点角色 | 角色描述 | CPU 利用率 | 内存利用率 |
---|---|---|---|
协调节点 | 请求集群的流量处理,网关 | 60% | 60-70% |
主节点 | 协调技术集群内部资源的分配 | 60-70% | 70% |
数据节点 | 存储数据 | 50% | 50-60% |
分段写入及查询场景下,架构选型分析
该场景因为日志的高峰期数据只会在夜晚固定时间段内进行大量写入,故而在一定时间段内,集群的各节点压力都比较大,白天仅提供查询,此时集群的整体压力较轻,仅有涉及查询流量的协调及数据节点压力较大。故而在做架构设计时,相较之前的架构,增加了两个协调节点的角色。
节点角色 | 角色描述 | 节点数量 | CPU | 内存 | 存储 | 存储介质 |
---|---|---|---|---|---|---|
仲裁节点 | 协调集群选举 | 1 | 2C | 6G | 50G | 对象存储 |
协调节点 | 请求集群的流量处理,网关 | 4 | 24C | 54G | 50G | 对象存储 |
主节点 | 协调技术集群内部资源的分配 | 2 | 24C | 54G | 50G | 对象存储 |
数据节点 | 存储数据 | 8 | 24C | 54G | 2T | 对象存储 |
在之前的基础上又增加了两个协调节点,负责应对处理晚上瞬间大流量数据的写入。
此外,增加两个协调节点,在应付白天大量数据查询场景时,也能做到更快的响应。在此种架构,未做任何集群调优策略的情况下,在面对半夜批量写入10亿级别日志数据时,写入速率在每秒15W-20W条数据左右,数据写入无延迟,数据查询也能做到近实时查询,毫秒级响应。各节点系统资源使用情况如下(此处统计的为日常情况下的均值,仅供参考):
节点角色 | 角色描述 | CPU 利用率 | 内存利用率 |
---|---|---|---|
协调节点 | 请求集群的流量处理,网关 | 50% | 50-70% |
主节点 | 协调技术集群内部资源的分配 | 夜间写入60-70% 白天查询 40-50% | 夜间数据写入 70% 白天查询 40-50% |
数据节点 | 存储数据 | 50% | 50-60% |
针对上述两种应用场景,也总结出对应的Elasticsearch集群在API层面的调优策略
PUT template/event template?includetype_name=true { "order": 2, "index patterns": "event-*" "settings":{ "number of shards": 4, "number_of_replicas": 1, } |
PUT ilm/policy/7days { "policy" : { "phases" :{ "hot" : { "min_age" :"Oms" "actions" : { "rollover" :{ "max_size" :"50gb" "max_age" :"7d" }, "set_priority" : { "priority" : 100 } } }, "delete": { "min_age":"7d", "actions" : { "delete":{ } } } } } } |
index.translog.durability: async |
index.translog.sync interval: 120s |
indices.memoryindex buffer size=20% |
indices.fielddata.cache.size:20% |
# Search pool #thread_pool.search.size: 5 thread_pool.search.queue size:100 # Write pool # thread_pool.bulk.size: 16 thread pool.bulk.queue size: 300 |
index.merge.scheduler.max thread_count=1 |
PUT template/event template?includetype_name=true { "order": 2, "index_patterns":"event-*" "settings": { "number_of_shards": 4, "number_of_replicas": 0, } |
该场景下,因为数据需要进行归档处理,将生命周期策略调整为 hot-cold-delete 三个阶段,数据在经过 cold 阶段后,会归档到日志中心专用的存储介质,通常为对象存储。
经实践,Elasticsearch在不同的存储介质下,读写性能差异很大,且在存储介质已决定的情况下,API 层面如何调优,效果都很有限。以下是经过测试后得到的数据,两种架构场景下不同存储介质写入速率对比:
API 调优前写入(NAS ) | API调优后写入(NAS ) | API调优前写入(对象存储) | API调优后写入(对象存储) |
---|---|---|---|
实时写入及查询场景 | |||
1.4w-1.6w/s | 2.0w-2.5w/s | 10w-12w/s | 15w-20w/s |
分段写入及查询场景 | |||
2.0w-3.0w/s | 3.5w-5.0w/s | 15w-20w/s | 25w-45w/s |
通过上述表中数据可以看到,不同场景下,影响数据写入的主要因素,一个是存储介质,一个是调优策略。但存储介质的影响更为关键,在实际实践场景里,只用到过NAS与对象存储,故而此处给出了二者的相关数据,可以看出,对象存储的写入速率是要比 NAS 的快很多的。
但 Elasticsearch 尤为推荐 SSD 存储,也曾看过 SSD 场景下,数据写入的情况,若是同样集群配置的情况下,写入速率是会是每秒百万级。此时,限制写入能力的,会是 CPU 跟内存,但是由于成本原因,很多金融领域行业并不能选择此类存储,不失为一种遗憾。
除此之外,Elasticsearch 本身的生命周期策略设置,需要根据实际情况去定。比如在实时场景下,由于数据要做到近实时,集群的主要压力就在于写入与查询,此时若设置过长的生命周期阶段,集群会消耗过的内存与 CPU 资源,去定时更新索引的生命周期状态,反而会影响数据的写入,得不偿失。故而生命周期策略就设置为 hot-delete,在保证场景诉求的同时,亦能满足索引数据管理的需要。
而在分段写入场景下,由于写入与查询是分开进行的,此时集群的压力是有限的,再加上该场景有数据归档要求,故而生命周期策略设置为 hot-cold-delete,数据在 cold 阶段会批量归档到对象存储中,归档完毕后,执行 delete 阶段,自动清理掉数据。由此观之,不同场景下,优化数据写入需考虑的因素是极多的,场景的诉求,硬件资源的限制,API 层面的调整,甚至还可能有网络层面带宽的限制,等方方面面都会影响到数据的写入。