窝窝团的ES经验教训总结
本文节选自研发解决方案介绍#基于ES的搜索+筛选+排序解决方案
ES 的几次事故和教训
1>误删数据
ES 的 Web 控制台权限很大,可以删数据。
有一天,一个开发者需要查询索引 mapping,他用 firefox 的插件访问,结果 Method 默认居然为 DELETE,如下图所示:
没有注意,于是悲剧发生了。
教训:
1)后来耀华咨询了长期运维ES的一些人,大部分都建议前置一个 ngnix,通过 ngnix 禁用 delete 和 put 的 HTTP 请求,借此来限制开放的ES接口服务。
2)这次的误操作,实际上是在没有给定索引的情况下,误执行了DELETE 操作,结果删除了全部索引。其实配一下 ES 是可以避免的,加入这个配置:
action.disable_delete_all_indices=true
这样会禁止删除所有索引的命令,删除索引的话,必须要给定一个索引 ,稍微安全一些。
2>mvel 脚本引发的ES事故
ES集群表象:
一天,ES 各个节点负载升高,JVM Full GC 频繁。
查看其内存使用状况发现,ES 各个节点的 JVM perm 区均处于满或者将要满的状态
问题原因:
头一天上线了商品搜索的一个动态排序功能,它采用 ES 的 mvel 脚本 来动态计算商品的排序分值。而 mvel 的原理是基于 JIT,动态字节码生成的,于是很有可能造成 perm 区持续升高,原因是它不断地加载和生成动态 class。
由于 ES 各个节点的 perm 区接近饱和状态,所以造成了服务器负载升高,GC 频繁,并进一步造成 ES 集群出现了类似于“脑裂”的状态。
经验教训:
引入新技术,还是要谨慎,毕竟如果真是 mevl 脚本引起的问题,其实线下做压力测试就能提前发现。
加强ES的监控。
虽然现在回过头来看,如果在第一时间重启所有 nodes,损失应该是最小的——但是王超认为当时采用的保守策略依然是有意义的,因为在弄清楚问题原因之前,直接重启 nodes 有可能反而造成更大的数据破坏。
3>mark shard as failed 的 ES事故
问题现象:
一天,打算对 JVM 参数和 ES 配置做了小幅度的谨慎调整。
凌晨 00:10 左右,维护者开始按照计划对 ES 集群的各个 node 依次进行重启操作,以便使新配置的参数生效(这类操作之前进行过很多次,比较熟练)。
1, 使用 http 正常的关闭接口,通知 174_0 节点进行关闭,成功。
2, 观察其余 node 的状态,几十秒后,ES 剩余的9个节点恢复了 green 状态。
3, 启动 174_0 节点。
——至此仅仅完成了 174_0 节点的重启工作,但紧接着就发现了问题:174_0 节点无法加入集群!
此时的状态是:174_0 报告自己找不到 master,剩余9个节点的集群依然运行良好。
于是用 jstat 查看了 174_0 的内存占用情况,发现其 ParNew 区在正常增长,所以他认为这次重启只是比往常稍慢而已,决定等待。
但是在 00:16 左右,主节点 174_4 被踢出集群,174_3 被选举为主节点。
之后,日志出现了 shard 损坏的情况:
[WARN ][cluster.action.shard ] [174_node_2] sending failed shard for [goods_city_188][0], node[eVxRF1mzRc-ekLi_4GvoeA], [R], s[STARTED], reason [master [174_node_4][6s7o-Yr-QXayxeXRROnFPg][inet[/174:9354]]{rack_id=rack_e_14} marked shard as started, but shard has not been created, mark shard as failed]
更糟的是,不但损坏的 shard 无法自动回复,而且损坏的 shard 数量越来越多,最终在将近 01:00 的时候,集群由 yellow 状态转为 red 状态,数据不再完整(此时损坏的主 shard 不到 20%,大部分城市还是可以访问的)。
临时解决办法:
首先对主站做业务降级,关闭了来自前端工程的流量。
维护者开始采用第一套方案:依次关闭所有 node,然后再依次启动所有 node。此时上面新增的 gateway 系列参数开始起作用,集群在达到 6 个 node 以上才开始自动恢复,并且在几分钟后自动恢复了所有的 shard,集群状态恢复 green。
随后打开了前端流量,主站恢复正常。
接着补刷了过去2小时的数据到 ES 中。
至此,故障完全恢复。
经验教训:
1, 此次事故发生时,出问题的 nodes 都是老配置;而事故修复之后的所有 nodes 都是采用的新配置,所以可以确定此次问题并不是新配置导致的。
2, ES 自身的集群状态管理(至少在 0.90.2 这个版本上)是有问题的——先是从正常状态逐渐变为“越来越多的 shard 损坏”,重启之后数据又完全恢复,所有shard 都没有损坏。
3, 由于是深夜且很短时间就恢复了服务,所幸影响范围较小。
4, 故障原因不明,所以随后安排 ES 从 0.90 版本升级到 1.3 版本。
ES 存在的问题以及改进
Elastic Search 在窝窝运行几年来基本稳定,可靠性和可用性也比较高,但是也暴露了一些问题:
1. ES 的更新效率,作为基于 lucene 的分布式中间件,受限于底层数据结构,所以其更新索引的效率较低,lucene 一直在优化;
2. ES 的可靠性的前提是保证其集群的整体稳定性,但我们遇到的情况,往往是当某个节点性能不佳的情况下,可能会拖累与其同服务器上的所有节点,从而造成整个集群的不稳定。
其实解决这个问题不难,两种方法:
增加服务器,让节点尽可能地散开;
当某个节点出现问题的时候,需要我们及早发现处理,不至于拖累整个集群。其实监控一个节点是否正常的方法不难,ES 是基于 JVM 的服务,它出现问题,往往和 GC、和内存有关,所以只要监控其内存达到某个上限就报警即可;
3. 没有一个好的客户端可视化集群管理工具,官方或者主流的可视化管理工具,基本都是基于 ES 插件的,不符合我们的要求,所以需要一款可用的客户端可视化集群管理工具;
4. ES 的升级问题,由于 ES 是一个快速发展的中间件系统,每一次新版本的更新,更改较大,甚至导致我们无法兼容老版本,所以 ES 升级问题是个不小的问题,再加上我们数据量较大,迁移也比较困难。

浙公网安备 33010602011771号