基于ElasticSearch的标签系统的架构治理
基于ElasticSearch的标签系统的架构治理
1. 背景
原有标签系统重度依赖elasticsearch,支持了公司70+接入方使用。支持了几个业务条线的客户分析及API服务。
整个Elasticsearch 集群共计存储了10T+的数据(无副本模式)。
整个ElasticSearch 集群涉及了几个场景的使用:
-
数据写入(宽表信息从Hive同步到ES)
-
用户通过平台进行客群的数量分析以及画像分析(统计某些维度的数据量)
-
API 服务能力, 对外提供客户维度的画像(通过search/get)
-
API 服务能力, 对外提供客群拉取的能力(通过_scroll实现)
我们遇到的问题:
-
集群在数据写入的情况下,因为使用bulk 的方式 load,导致集群的search能力和 _aggs 能力性能急遽下降,导致了API服务的不稳定,甚至是不可用。
-
集群在_scroll 情况和用户画像的情况下, 内存急速消耗,导致长时间的GC,进而影响API服务的可用性和业务使用
-
索引SHARD 分配不合理,极其容易导致 _search 导致的负载过高,甚至 shard 丢失,进而Elasticsearch 集群变红,导致服务不可用。
-
Elasticsearch 的写入只能进行限速的导入,从而导致数据的时效无法达到业务的要求。单一大索引,导入时间在40小时+, 从而导致业务时效口碑较差。
-
若干大索引同时写入过程中,集群负载过高,导致集群直接飘红,无法服务。因为若干导数作业的时序性无法保证,所以集群的稳定性只能靠人为自行监控排查。因为事件经常在半夜,苦不堪言。
2. 分析
集群飘红
集群飘红,是多因素导致的。
ElasticSearch集群飘红的原因有很多。总的来说,可以分成3类。
1. IO过高
IO过高一般有两种,一种是iowait多高,这种情况下需要更好的ssd硬盘。即便是SSD硬盘的情况下,我们也同样碰到了IO过高。(公司内网不方便截图)。当然这种IO过高,定位了原因是文件系统在做其他读写,进行了限速写入就恢复了。(在HDD硬盘上,这种IOwait 会更多)
另外一种是 ES进程内的文档插入/更新参数不合理导致的IO过高。如bulk的byteSize设置不合理,refreshInterval 设置成1s 导致的Segment Merge 问题,以及Replica设置成3导致的副本分发IO问题(translog)。
2. 流量过大
流量过大 ,主要是上游未做保护的流量穿透。比如_search 高峰可达30w/s。这种请求的堆积,正常情况下,只会堆积请求,但与写入请求同时发生时,容易引起FGC,进而导致节点脱离。
3. GC 导致的节点脱离
GC 算法需要优化, 在JDK11 的新GC算法前, CMS和G1的表现算是比较差的。CMS经常会GC时间过长,导致节点的健康检查无法及时通过,进而被集群判定为挂了,导致集群飘红,影响业务。
3. 解决方案
从上述各场景定性的分析,按照场景和资源消耗情况进行整理出来大致的方案。
为啥不定量?因为No Measurement! 而且在资源不稳定的情况下,各种数字已经失真了。
因此改进方案分成4路分别改进:
-
Hive2es 工具改进,以减少对ElasticSearch 负载压力为根本优化目标。提升速度时效。
-
增加新的ES集群,物理隔离若干大索引。可以有效隔离彼此的业务影响。
-
对原有依赖ElasticSearch的scroll 方案进行架构变更以及整体设计。根据业务用例,我重新设计了异步取批的数据服务。
-
对单个用户的search 接口重新使用get实现。 (在并发高的情况下,比如_searchById 并发高达16w/s时,任务会堆积,从而导致接口会变慢)
4.成果&收益
重点产出成果有三个:
-
Hive2ES 工具。 参考DiDi 的 fastindex 实现。可以把原来40h+的导数任务并行到2h。同时对Elasticsearch的负载由原来的Cpu&io 变成了纯IO影响。 后续会单独来描述这一内容
-
异步取批数据服务。 可以稳定的提供取批功能,原来平均取批时间从20min到5min。并且稳定高效,支持断点续传
-
画像服务产品。 独立的画像数据服务。提供高性能的key value 查找服务,支持定制化DSL定义,可以跨集群/跨索引/跨接口的提供服务。