aerospike节点重启

2014-12-25

前几天我们的aerospike集群一个结点重启,差点造成一次线上'事故'。

事情是这样的,我们一个10个节点的aerospike集群,把其中一个节点重启了。然后就观察到发现了严重的数据不均衡,重启的那个节点数据不停地涨。其它节点大概在一个25%到30%之间的内存使用量的样子,而重启的那个节点内存使用量飙到了60%以上,而且还一直在涨。

这样不停涨下去肯定要暴掉,按现在设置的hwm参数到数据量90%的时候服务就会拒绝写请求,吓得一身冷汗。赶紧去排查问题。

先是仔细观察监控面版,读入是10w多的qps,观察到平时的写入tps大概在4000多,单个结点400多。但是周期性地,重启过的那个结点会有1w8的写入的tps。这个周期大概在5分钟左右,只在这个节点上有这种大量的写入。

去对比正常节点上的各项参数,和这个不正常节点上的参数,发现其中迁入迁出一项,migrates incoming对正常结点只在0或者1等很小的值,而对重启的那个节点,migrates incoming是9,而migrates outgoing是510多。分析一下就发现问题是在这里的,写入的高tps是来自于其它节点向重启的节点在迁移数据。这要从aerospike的迁移和rebalance的机制说起。

aerospike的数据分片是划了4096个虚拟的partition,每台机器会负责一部分的partition。查询过程是先确定数据被hash到哪个分片,再看这个分片是由哪个节点负责的。如果有节点挂掉了,那么集群会进行调整。假设原来是10个节点,挂掉一个。变为9个节点,那么数据就需要重新分布了。尽管一个优秀的算法会追求尽量减少需要迁移的数据量,但是这种数据迁移是避免不了的。先不考虑分片副本的情况,挂掉的那个节点负责的分片需要重新由这9个节点来分摊。

我们的情况是节点重启了,也就是它再次加入到集群中。这次,又需要一次重新分布,它要从现有的9节点集群中分摊一部分的分片。所有9个节点都会向它写入数据,这就解释了前面的1w8的tps。当然这个节点中的数据应该也是要向其它9个节点迁出的,但似乎是迁出比迁入慢了一步,其它9个结点都在向它写入数据,导致它的数据量一直在涨,使用超过60%了。

aerospike有一些参数,是迁移相关的设置。执行迁移任务的线程数,迁移任务的优先级,迁移队列的高低水位,迁移的休眠时间等等,这些都是可配置的。迁移任务的优先级不能设置得过高,否则就影响production正常读写服务了,但是也不能过低,迁移会很费时。迁移队列的高低水位,是控制当迁移任务的队列比较长了,就要执行迁移,而当队列下降到一定程度,就优先执行其它操作。休眠时间是迁移任务会周期性地执行,前面观察到的高tps是一阵一阵的,就是因为迁移是周期性地执行的。

我们的节点在内存使用量达到118G的时候终于停了下来,开始迁出大于迁入了。这个异常节点中的数据量慢慢下降,趋向于平衡了,虽然捏了一把汗,但最终没成为一次事故。

这里思考几个问题。

能不能不要数据重分布?假设我们需要将节点下线维护,然后上线。好的情况应该是只有部分业务受到影响,下线节点负责的分片数据不可用,不需要重新rebalance数据的。但答案是,aerospike不能。aerospike做得很智能,节点之间由一个fabric模块维护着通信,有一些参数会设定超过多长时间不可用就将节点从集群down掉,重新分布数据。

为什么要保留一定比例的存储使用量?这是官方推荐的做法,这里我们已经亲身体验了一回。如果现在不是使用率在30%以内而是到达70%,那这一次肯定就成为一次事故了。这个场景中是向重启的节点迁入数据的速度大于从该节点迁出数据的速度,导致的单个节点数据使用量暴涨。应该还有一些其它场景也会,所以保留一定比较的存储使用量是必须的。

节点故障后恢复,一致性是怎么处理的?假设一个节点down了,负责的分片由其它节点负责了,比如说1080号分片的数据。当该节点复活之后,它说我这里有1080号片的一些数据,这个数据可能是跟现在集群中的1080号分片中的数据冲突的。aerospike的做法是,数据是有一个generation的,由generation来区分。

好吧,就写到这里。顺带说下,最近又发现aerospike的Go客户端的一个bug,我提了issue,还没修复。不知道要踩多少坑才能用好一个产品。不过还是很高兴地看到我们的SSD化,现在我们已经迁移了部分数据,aerospike存储了100多亿的cookiemapping的记录,SSD存储使用量已到2T多(换作原来就是这么多的内存哦!),这一点一滴的改变,都将成为公司的技术竞争力。

aerospikessd