数据库内核月报

数据库内核月报 - 2018 / 02

Influxdb · 源码分析 · Influxdb cluster实现探究

Author: fengyu

背景

Influxdb cluster在0.12版本的release notes中声明,将cluster代码闭源,并且将cluster版本作为商业版售卖。

虽然cluster版本毕源已经一年多的时间,从目前官网中release notes来看,总体的设计没有发生变化。

本文主要探讨influxdb cluster 0.11版本的实现细节,学习参考。本文将参考官方博客中的一篇设计文稿,同时参考Influxdb最后的一个cluster开源版本的源代码,分析influxdb cluster实现,水平有限,欢迎指正。

参考博文 :

https://www.influxdata.com/blog/influxdb-clustering-design-neither-strictly-cp-or-ap/

https://www.influxdata.com/blog/influxdb-clustering/

https://docs.influxdata.com/enterprise_influxdb/v1.3/concepts/clustering/

https://docs.influxdata.com/enterprise_influxdb/v1.3/guides/anti-entropy/

InfluxDB Clustering Design – neither strictly CP or AP

cluster设计约定

下述为官方的influxdb cluster设计约定。

需求

cluster design

系统架构图

image.png

Cluster Metadata – CP

首先解释这个CP的含义是CAP理论中的CP,C: consistence一致性 , P表示PARTITION TOLERANCE,CP表示cluster 元数据的服务,更加着重保障系统的一致性。

图中上半部分是metadata node, 存储元数据包括:

每个metadata 节点会通过一个简单的http 对外提供服务,其中raft的实现是: https://github.com/hashicorp/raft,raft底层数据存储使用Boltdb。

每个server (datanode)会保持一份cluster metadata的数据拷贝,会定时调用http接口获取存量元数据感知元数据的变化。当request请求到该data node时,如果cache miss, 此时调用metadata获取对应的元数据。

Cluster Data Write – AP

AP的含义是CAP理论中的AP,表示系统系统设计着重保障系统的可用性,舍弃一致性。下述介绍一个write请求的访问流程。

Shard Group

image.png

前提:

Shard Group是什么?

image.png

  type ShardGroupInfo struct {
  	ID        uint64
  	StartTime time.Time
  	EndTime   time.Time
  	DeletedAt time.Time
  	Shards    []ShardInfo
  }

一个Shard Group映射多个ShardInfo。并且Shard Group有StartTime, EndTime等属性。

type ShardInfo struct {
	ID     uint64
	Owners []ShardOwner
}

每个ShardInfo属于多个ShardOwner,如用户设置数据需要写入2份,那么每个ShardInfo既对应存在两个ShardOwner (data nodes)。

Steps:
  1. 根据写入point的timestamp, 获取写入的数据属于哪个shard group。如果shard group信息在data node中不存在,调用metadata service获取。
  2. cluster metadata service会负责规划这些数据分配到哪些节点上。shard groups一般会在写入请求到来之前提前创建,防止批量请求的数据量过大冲击到cluster metadata service。
  3. measurement name和tagset相加进行hash并且根据shard group中ShardInfo的数量进行取余,那么最近的一些时序数据就会平均写入到每一台服务器上,分散写入压力。注意此时的hash算法不是一致性hash, 原因是

Write Points to Shard

write定位到对应server的shard后,开始写入到shard流程,如下图所示

image.png

每个写入需要设置一致性级别 (consistency level)

值得注意的是:

Hinted Handoff

下面我们详细描述下Hinted Handoff的工作机制。

Hinted handoff 帮忙我们快速恢复这些短时间内的写入失败,如server 重启或者由于gc 中断, 高查询导致系统负载过高而导致server的临时不可用。

在我们先前示例中,当写入到达server 1后, 会尝试写入到server 2, 3, 4. 当写入4失败时,server 1的hinted handoff会不断尝试将失败的数据写入到server 4中。

hinted handoff的实现机制:

image.png

image.png

image.png

type Config struct {
	Dir              string        `toml:"dir"`
	MaxSize          int64         `toml:"max-size"`   		// 默认一个队列最大大小为1G
	MaxAge           toml.Duration `toml:"max-age"`		    // 默认Age为7天
	RetryRateLimit   int64         `toml:"retry-rate-limit"`	// 重试的频率,单位为bytes per second. 默认不限制 
	RetryInterval    toml.Duration `toml:"retry-interval"`	  // 重试失败的时间间隔,按照指数级增长直到达到最大重试间隔。默认1秒
	RetryMaxInterval toml.Duration `toml:"retry-max-interval"`		// 重试最大间隔,默认1分钟
	PurgeInterval    toml.Duration `toml:"purge-interval"`			// 清理间隔,既将由于过期,或者不活跃的节点的数据做清理,默认1小时
}

Anti-Entropy Repair

Anti-entropy repaire确保我们能够达到我们数据的最终一致性。集群中的servers 会定期的交换信息确保他们拥有同样的数据。

这么设计的原因,如官方在开头中对时序数据使用场景的假设:

  1. 所有的数据写入都是针对最近的时间。所以老的shard不应该会有频繁的数据的变更。

非常遗憾的是,0.11版本的cluster源代码并没有实现Anti-Entropy Repair的功能。具体实现细节不做介绍。

Conflict Resolution

当存在update同一条数据的场景时,就会出现冲突的情况。influxdb cluster解决冲突的办法非常简单:the greater value wins。这种方案使得解决冲突的代价非常低,但是实际上也带来了一些问题。

如:

  1. 当一条update请求到server 1,需要更新server 1, 2, 3三副本中的数据。此时update 在server 3上执行失败了,那么数据在server 3上实际上仍然为老数据。
  2. 后续当对同一条记录执行update操作时,此时三副本的server执行全部成功,此时server1, 2, 3上面 的数据全部被update成功。
  3. 第一条update记录在server 3上通过hinted handoff模块写入成功。此时server 1,2,3上面的数据将会不一致。最终通过Anti-Entropy Repair模块将数据做最终校验,按照文中描述可能会取两次update更大的值。实际上update操作的结果是不可预期的。

influxdb cluster的设计基本不过多考虑这种时序数据中少见的delete和update操作。但是将update/deletec操作的一致性级别设置为ALL保证delete和update成功是减少上述问题发生概率的方法(即使设置成ALL,如果一旦delete失败也是有不符合预期的情况存在),但是设置为ALL后服务的高可用性会有一定的影响。

Design Conclusion

官方对influxdb cluster的设计概述:

influxdb cluster的设计既不是纯粹的CP或存粹的AP系统,cluster一部分是CP系统,但是数据保证了最终一致性。一部分是AP系统,如果出现较长时间meta nodes和data nodes之间的分区,可用性是不能保证的。上述设计历经influxDB cluster的三次迭代,根据实际的需求做了很多的trade-offs,设计更多的倾向cluster需要实现的最重要的目标: 数据可以水平扩展和写入更低的开销。

总结

虽然非常遗憾cluster后续版本没有开源,但是influxdb cluster总体设计已经非常完善,并且开源出来的0.11版本也是非常具有参考价值。

目前开源的Influxdb cluster 0.11 版本缺乏能力包括:

如果能够补齐以下两块能力,你觉得使用influxdb cluster符合你的业务场景么?你会用么?