大规模存储系统成本性能优化的一些方法

目前(2021年)的主要工作是参与公司自研对象存储的开发和维护,记录一些常见的成本优化思路。因为投入产出比的原因,不一定所有企业都能够落地。

挑选的都是可以从公开渠道找到相关信息的方案,不涉及企业内部技术机密。

内容很少,想到啥更新啥。

SMR 硬盘

SMR 硬盘是利用叠瓦技术提升机械硬盘存储密度的硬盘,存储模型可以简化为:磁盘上有若干个分区,每个分区可以划分为 m 个有顺序的 Block,第 i 个 Block 的写入( 0 < i < m ),会导致第 i+1 个 Block 数据的损坏,为了避免数据丢失,会需要在写入前,备份第 i+1、i+2 … m 个 Block,完成第 i 个 Block 的写入后,依次写入第 i+1、i+2 … m 个 Block。即随机写有较大概率会导致写放大。

显而易见的,可行的优化方案是记录已经使用过的 Block,并尽可能保证按顺序写入,当前分区仅使用前 k 个 Block 时( 0 < k < m),写入第 k+1 个 Block 并不会导致写放大。

很长的一段时间内,大部分文件系统都不会感知磁盘 SMR 特性,并进行针对性优化,大部分时候是由磁盘驱动对上屏蔽相关信息,执行重写操作。但由于磁盘驱动难以感知文件系统和应用信息,可能导致比较明显的性能退化,主要应用在消费级领域 ,毕竟小白的钱不骗白不骗

企业级硬盘领域,目前(2021年)SMR 硬盘占比仍然相对较少,部分硬盘厂商提供了 Host Managed 模式的 SMR 硬盘,对于这类模式的硬盘,文件系统或应用可感知底层 SMR 硬盘特性,进而针对性优化。主要适用于 LSM Tree Compaction、WAL 等以顺序写入为主的场景。

Linux 内核也引入了名为 ZBD(Zone Block Device)的机制对 SMR 和 非 SMR 硬盘进行抽象,其抽象为:存储设备被分块为多个 Zone,每个 Zone 是一组连续的 LBA(Logical Block Address,逻辑区块地址),Zone 被分为不同的类型:常规区域(Conventional Zone),可以随机读写的区域;连续区域(Sequential Zone),可以随机读,但只能追加写,修改数据需要先清空整个区域内的数据。

通过存储引擎对 SMR 硬盘的适配,可以在大部分场景不显著降低性能的前提下,降低存储成本。但目前(2021年)企业级 SMR 硬盘不够普及,能够批量出货的硬盘厂商只有希捷、西数在内的少数几家,提供兼容性保证的服务器厂商占比更少,一般只有大型企业才有能力落地。

相关信息:

类似实践:

小对象聚合 EC

常见对象存储降低成本主要依赖 EC(Erasure Coding, 纠删码) 算法,写入时将数据分为 m 份,EC 编码为 m+n 份,如 5+2、28+4,分散存储到 m+n 台设备上;读取时,获得任意 m 份即可恢复完整数据;综合副本数 m+n / m,写入时最小 iops m+n,读取时最小 iops m。

另一类保证数据可靠性的方案是副本机制(Replica),写入时将数据复制到 m 台设备上,读取时,获得任意 1 份即可完成请求;综合副本数 m,写入时最小 iops m,读取时最小 iops 1。

EC 算法可以大大降低数据的存储成本,但是以 Object 为单位(其实往往是将单个大 Object 切分为多个 EC 组)的切分,会导致读写 iops 放大,对于 HDD 存储集群来说,相对较为奢侈。

一种可行的优化思路是,将多个小对象聚合后进行 EC 编码,再分散存储。假设有 x 个小对象聚合后 y+z 编码,则每个对象平均写 iops (y+z / x),读取时,只要单个小对象的数据不跨越 EC Block 边界,iops 仅为 1。存储成本与 EC 方案相等,但 iops 可以接近副本方案。但是在部分对象删除时,可能会有写放大,且会少量增大元数据体积。

大部分对象存储服务对于 PUT 请求要求在线响应,所以直接在写路径上实现聚合 EC 可能存在一定挑战,可行的方案是写入时以副本机制写入,离线任务时再进行聚合 EC 编码。

虽然以小对象举例,但实际上对于大对象,也有类似效果,但大部分场景下优化不明显,且 GC 时写放大会更加严重,往往不采用。

类似实践:

分级存储/混合存储

目前相对 HDD,SSD 虽然有明显的性能优势,但单位存储成本较高。对于 IOPS 不高但容量需求较大的场景来说,HDD 仍然是较为主流的选择。

即使同样是 HDD,选择的复制策略不同,也会很大程度上影响读写性能。总体上表现出 “性能好的成本高,成本地的性能差"的特性,可以通过组合多层存储,一定程度上在成本和性能上做取舍,提升综合效益。

对于写路径,常见的方案是先将零散请求写入较快的存储层,如 SSD/副本,根据一定的策略将数据离线写入较廉价的存储层,如 HDD/纠删码。通过较快的缓冲区,提供更优的写路径响应延迟和吞吐;通过 batch 等方式,利用 HDD 顺序写入性能高、小对象聚合 EC 等特性进行优化。

对于读路径,一般只能寄希望于业务请求的特定模式,一般是时空局部性,使用缓存和预读提升平均读取延迟和总吞吐。除了常见的 SSD 做 HDD 缓存外,另一个思路是,冷数据用较为激进的 EC 策略存储,上层维护一个单副本的部分数据集做缓存,相比小文件离线聚合 EC 来说,这个方案实现更加简单。

以上策略可以应用层实现,也可以利用 Raid 卡或 Linux Bcache 直接组合 SSD 和 HDD。

相关实践:

提升综合利用率

虽然有诸如 EC、Compaction 等重计算任务的存在,但对于冷数据为主或存算分离较为彻底的存储系统来说,CPU 往往相对空闲。大型企业可能可以通过定制机型,选用较为孱弱但更廉价更节能的 CPU,降低总生命周期拥有成本;更常见的将 IO 密集应用与 CPU 密集任务混部,让空闲的 CPU 发挥价值。

对于非自建机房或机房容量较为紧张的企业来说,机位成本也是不可忽视的一环,通过提升单机存储密度,在更小的机箱里塞下更多的存储介质,可以进一步降低存储成本。如使用容量更大的硬盘,定制盘位更多更紧凑的服务器等。不过需要注意的是,将更多的数据放置在同一个故障域内,意味着恢复速度不变的情况下,单盘/单机故障的数据恢复时间会变得更长,相应的,服务可用性甚至数据可靠性都会有所下降。

相关信息: