Cassandra 在 360 的实践与改进

file
分享嘉宾:王锋 奇虎360 技术总监数据库

文章整理:王彦缓存

内容来源:Cassandra Meetup安全

出品平台:DataFunTalk微信

注:欢迎转载,转载请留言。数据结构

导读:2010年,Dropbox 在线云存储在国外被用户熟知,同时国内如360、金山、百度等各个厂商也都陆续推出了自家的网盘类产品;而在 "360云盘" 背后的存储技术支撑之一就是以 Cassandra 为基础的云端存储方案。自此,Cassandra 在360实现技术落地和大规模生产应用,并被持续改进优化,最终造成高峰时期超 10k+ 物理节点的使用规模,成为互联网公司中 Cassandra 生产环境落地规模最大的公司。架构

本次分享的主要内容是 Cassandra 在360的落地实践过程当中遇到的问题,以及一些重要的改进和优化,主要包括:并发

Cassandra 的特色简介app

Cassandra 在360的选型运维

Cassandra 在360的应用场景dom

Cassandra 在360的技术演进

——Cassandra 的特色简介——

Cassandra 大体有如下的特色:

file

Cassandra 彻底无中心化设计使得其具有极高的可用性和可平滑的拓展性,而且具备模式灵活,多数据中心,范围查询,列表数据结构,分布式写操做等优点:

❶ 因为其架构在中小规模部署时不须要主节点,相较于彻底中心化的分布式存储设计具备更优的成本优点,从3台物理机开始一直拓展到几百台物理机,都可彻底不停服状况下平滑拓展,整个过程只须要把拓展节点的进程启动加入集群;

❷ 模式灵活使得 Cassandra 能够在系统运行时随意添加或移除字段,这是一个很惊人的效率提高,特别是在大型部署上;

❸ 多数据中心是指能够调整节点布局来避免某一个数据中心失效,一个备用的数据中心将至少有每条记录的彻底复制;

❹ 范围查询是指若是你不喜欢所有的键值查询,则能够设置键的范围来查询,对于每一个用户的索引,这是很是方便的;

❺ 分布式写操做是指有能够在任何地方任什么时候间集中读或写任何数据,而且不会有任何单点失败。

除了以上几点,Cassandra 还有以下的优势:

❶ 海量数据,随时在线,分布式数据库,性能极优

❷ always online,无中心,无单点故障引起抖动

❸ 节点对等,配置一致,线性扩展,易于维护

❹ cql/sdk 能力,易用性好,开发者 & DBA 快速上手

❺ 功能强大,主要有如下几点功能,多 DC 两地三中心,在线更改 schema,丰富数据结构,丰富的索引,监控及工具。

——Cassandra 在360的选型——

file

选型之始,咱们总结评估了云存储的技术需求特征和当时可承载大规模数据的分布式 K-V 数据库——Cassandra 和 HBase,最终权衡以后,使用 Cassandra 作为主要在线存储。对于 "网盘/云盘" 类产品,其主要流量特征为 "写多读少",要求服务可靠性和数据安全性极高,基本不可容忍服务中断和数据丢失的状况。具体选型分析以下:

❶ Cassandra 相较于 HBase,前者是彻底无中心设计,然后者 ( 包括依赖的 HDFS ) 总体来看是强中心化设计,所以 Cassandra 与生俱来不存在关键单点故障影响服务的问题;

❷ Cassandra 使用最终一致性策略,而非 HBase 的强一致性策略,配合读写策略的处理,Cassandra 能够在确保数据安全性、可靠性、一致性的前提下,出现节点宕机而不须要恢复时间,集群读写不产生任何停顿,而此场景下,HBase 须要等待 region 从新分配过程,而这个过程大概会有数秒至数分钟的待分配 region 不可读写;

❸ 从技术细节上,虽然两者均采用了 LSM 的架构,但 Cassandra 直接操做本地磁盘,而 HBase 须要依赖 HDFS 共享存储,加之上述所说的架构设计差别,同等基础设施性能的 Cassandra 写入性能优于 HBase 近乎一个数量级,读性能基本持平。

综上所述,Cassandra 能够更好的适用于云盘在线场景。

——Cassandra 在360的应用场景——

file

基于360云盘使用 Cassandra,云盘从15台机器一直到14000+台机器,应用场景主要是我的数据,本身产品中间的图片,内部视频对象等;在2015年,360云盘转型为企业云盘,机器数量就降低了,到2018年,智汇云又继续前行,目前机器差很少是3000左右的规模,以上是360的应用场景。

——Cassandra 在360的技术演进——

file

Cassandra 自2010在360开始调研技术落地;2011年使用 Cassandra 0.7.3做为基础版本应用于生产环境;2012年完善数据可靠性和安全性,实现不停机和不单纯依赖读修复的数据快速恢复;2013-2014年以节省成本为目的,实现可擦除编码技术应用于 Cassandra,在确保数据安全和可靠性的前提下实现成本下降60%;2014-2015年面对超大规模集群的超复杂性问题,实现运维自动化,集群具有自主自愈、自主风控等自主运维能力 ( 近 1w5 物理节点,89个集群,两人运维 );2018年,咱们发现 Cassandra 社区版本与360版本至关因而不一样场景异曲同工 ( 社区为轻 Value,360为重 Value ),而且社区不少好的思路很是值得考虑,所以咱们从新调整研发策略,与社区共同成长。

file

Cassandra 是一种无中心的系统,对于消息的广播,有一些规模的限制,基本单节点到600台的时候就差很少了,当时云盘的集群规模,单集群是600台,Cassandra 集群规模达到了88个,磁盘使用率达到了90%,主要是为了成本考虑,把磁盘使用率达到了90%。这其中用的是预先划分 range,毕竟当时没有 VNode,使用预先划分首先是使用 RandomPartitioner,使用例如 hash,md5 让数据随机打到环上,这个是使用最多的;还有一种是 OrdePerservingPartitinoer,这是一种保序的方式,把一些 key 保序的存在环上,文件 I/O 使用的 standard 跟 Mmapped,Mmapped 理论上是减小内存拷贝,对性能很好,可是若是数据量涨到80%到90%的时候,Linux 内核页表的开销占用量很大,因此最后放弃了 Mmapped 的方式,使用了 standard 的方式。

file

对于 Cassandra 的改进,第一个就是进行可靠性的改进,使用 Local Repair 跟 Backup。影响数据可靠性的因素有:

❶ One/Quorum 存在新增副本不足的问题;

❷ 磁盘/扇区故障:文件损坏、数据丢失 ( 月均故障25-30块 );

❸ 现有数据恢复机制存在不完善之处。

因素 ❶ 是第三副本是否能够成功写入的问题,使用非 ALL 策略写入 Cassandra 时,只要知足写入策略即返回成功,例如 quorum 级别写入3副本数据,当两个节点写入成功即返回写入成功,虽然原始设计为了保障第三副本写入成功使用 hintedhandoff 机制来保证,但程序设计最多能支撑3小时的时间,虽然该项可配但也受限于接入节点的存储容量,所以360针对此问题作了优化,研发 proxycheck 功能将未成功写入打散到全集群,当故障节点恢复时,基于 proxycheck 会修复残缺副本;

因素 ❷ 是磁盘故障,虽然小规模磁盘不多见磁盘损坏,但对于极大规模的存储系统来讲,磁盘故障就变得不可忽略了,而 Cassandra 的架构又决定了若是磁盘损坏形成了副本残缺很难发现,只能等待读修复触发或者 repair 工具修复,但对长时间不读取的冷数据很显然存在较大数据风险;

因素 ❸ 是修复机制,不管是因素 ❷ 致使的仍是其余问题形成的数据残缺都须要恢复机制尽快恢复数据,但 Cassandra 读修复对冷数据不友好,repair 工具会耗尽整个集群的资源,对于这些挑战,除了读修复,咱们实现了一套至关于 RowRepair 的机制。

file

首先来讲一下文件/磁盘的自动摘除, 存在的问题主要有两点,一点是读写异常,SEEKIOException 影响正常读写,另一点是各类修复机制,Compact 机制执行失效,针对以上的两点问题,主要采用了基于文件异常访问次数的统计,摘除故障文件数据比重,外部发现基于 SmartCtl 规则反馈,将以上的问题反馈到系统中,就能够精确的知道哪块磁盘有哪些问题。

file

修复磁盘故障摘除,此处针对的是全量数据的磁盘故障摘除,使用全盘数据扫描恢复的目的主要有两点,一是用来解决全量文件,因磁盘故障/文件损坏等缘由带来的副本不足的状况,二是文件/目录/磁盘摘除,触发后台主动副本修复。全盘数据扫描修复,从 Range 的开始,三个节点都读数据,若是数据存在冲突,就使用另外两个节点去解决数据冲突,最后把数据恢复。每一个节点都会附一个 range,range 的主要做用就是从三个节点上把数据取过来进行比对,而后把解决冲突的数据恢复掉,另一种方式使用 KeyScan+Read-All,使用 KeyScan 拿到的是一些 key,对于大量的插入,像云盘用户是大量的插入比较多,删除的操做不多,这种场景下数据存储使用的是 key-value 的数据格式存储,这种状况下,若是节点上丢掉了哪些数据,能够直接使用 key 来修复这些丢掉的数据。经过这两种方式能够解决文件丢失或者损坏的问题。

file

解决了全量数据,接着解决增量数据的检查修复问题。增量数据检查修复主要存在如下三个问题:

❶ 如何保证新写入的数据副本是足够的 ( 拒绝/超时 )

❷ 如何弥补 Hinted handoff 的缺点 ( 时间窗口 )

❸ Quorum 写存在 W<N

针对以上问题,Hinted handoff 对于 i/o 负载或者 i/o 假死没有考虑到,这种状况下,Hintedhandoff 没有去把出问题的东西记下来,时间窗口存在的问题是若是超时了,丢失的数据可能就记录不下来,因此须要把这两种状况记录下来,以便更好的解决增量数据存在的问题。其原理是:若是提供两种方式,第一种若是 proxycheck 把 value 记录进来之后,数据有问题,能够直接使用另外的副本进行数据修复,还有一种若是不记录的话,可使用 all 级别读修复来对数据进行恢复。使用 Proxy 节点负责记录副本不全的 row,超时拒绝致使的三个副本可能只写成功了两个,这种状况也须要记录下来,这种状况下,实时的去作数据的恢复或者副本的补全,使用 proxycheck 表来存储辅助的 Keyspace,把全部检测到的副本不足的数据都记录到这张表中,Proxy 节点还用于记录数据的修复,把数据存储,proxycheck 用了两副本,这样作会加大系统的开销,可是数据的可靠性获得保证。

file

数据的恢复,涉及到存储,同时,还须要用到数据的备份。当时没有所谓的多 DC 方式,都是自研的备份系统,当时 Cassandra 的集群数量有88个,若是采用 Cassandra+Cassandra 的主备模式,那将又是88个集群,这是对运维和成本的巨大挑战;所以咱们选择了在极大规模场景下扩展更好的 HBase 做为备份存储,使用 Cassandra ( 主 ) +HBase ( 备 ) 方案,这样全球88个集群数据备份集中至四大备份中心。大量的数据备份,常用的方式就是消息队列,数据的汇聚会增长运维的成本以及数据的落地而后再去作,这样操做的话,延时会比较高。因此在 Cassandra 中作了一个机制,每一个节点负责本身的 range 管理,能够记录到本身的缓存表中,从缓冲表取出来备份到数据中心,使用 Thirft 接口,HBase 跟 Cassandra 的接口彻底是兼容的,这样设计 HBase 备份中心就至关于一个 Cassandra 的数据中心了,若是数据大量丢失,或者数据出现大量的错误问题,能够直接无缝切换到 HBase 上提供服务,而后再使用 HBase 备份的数据慢慢恢复丢失的数据,用户彻底不会感受到服务异常,提升了用户的体验。

file

前面介绍的是数据方面的问题,下面介绍下如何提升磁盘的利用率也就是下降成本。主要是利用虚拟目录来提升磁盘的利用率,磁盘的利用率提升主要问题存在两点:

❶ 节点数量大,SSTable 文件多,磁盘空间致使没法作 major 消重;

❷ SSTable 文件数多,Scan 操做致使 CPU 消耗严重。

对于这两个问题,当时磁盘的利用率达到50%就没法再提升利用率,继而咱们采用了分而治之的思想,把一个大 range 使用 Daily—Compact 完成数据 SubRange,切分为几个小 range,每一个 range 表明一个目录,因为切分之后,数据量变小,每一个 range 均可以作本身的 major,能够把重复的部分都清除掉 ( 可是若是在磁盘利用率90%以上,作一次 major 就很消耗 CPU 性能 ) ,这样作之后,对于 Scan 请求定位 SSTable 打开的文件会更少,效率就会更高,速度也会更快。

file

避免写放大的问题。对于如何减小写放大问题,主要存在如下两个问题:

❶ 原有的 Compaction 机制 ( SizeTiered/Leveled ) 较难避免数据重复参与 Compaction 的问题;

❷ 尤为在 SizeTiered 按文件大小分组 Compaction,插入删除频繁的业务难以消重。

针对上述问题,咱们采用给 SSTable 增长 level 概念。正常的是给每层的数据从 level 0 -> level 2,到 level 2 后,compaction 就不会参加,也就说最多作两次。360对于这一块作了以下的改进:让每层的 compaction 结合虚拟目录,在 level 0 作 compaction 的时候,分红各类各样的虚拟目录进行 subrange,subrange 里边再去作 compaction,这样的话,就至关于虚拟目录没有重复的数据出现,控制文件参与 compaction 的次数,经过这两种方式,使磁盘的利用率达到了90%左右。

file

成本压力。基于成本的考量,使用了 EC 的方式,让3副本变成了1.4个副本,在较少副本数量的同时保证数据的可靠性,同时从数据可用性上考虑的话,数据可用性基本保持如下两点就能够:

❶ 副本方式,也就是连续3节点磁盘故障,数据必丢失;

❷ 条带方式,相邻的14节点故障任意4个数据仍可修复。

对于这个内容,EC 是把原有的数据进行块切分,算出校验块,而后校验块打散到整个集群中,若是丢失了几个块,能够用其余的10个块进行修复,再把分散的块 key 存储到 cfindex 的表中。对于前边的条带方式,主要使用切分 value,value 采用的是 512k 切成等份的4等份,能够获得4个校验块,须要所有打散到不一样的数据块上,好比下图中的 k13,k14 不能放到一台机器上,这样才有意义,一旦数据丢失了,还能够方便恢复,若是四个块在一台机器上,坏了两台机器就无法恢复了,key 的数据有两部分,一个是元数据,一个是条带数据。元数据仍是保持多副本的形式,可是算出来的条带数据其实是按环分布,分红单副本的方式去存储,这样其实就能够达到三副本到1.4副本,编码能够在线调整,还可使用指令集加速,经过指令集对 EC 进行加速,这块比较难的问题是如何把 Key 值分散在整个环上,并且还在不一样的机器上,若是使用 Md5 算出来 value 值看成 key 值,仍是有可能 Key 值存储在一台机器上,因此仍是采用了 OrderPreservingPartitioner 保序的方式去存储。

file

接着作了一个 Keyspace 级别的 Patition 策略,之前的 key 存在如下问题:

❶ RandomPartition 能够解决大部分 Key 随机分布的问题;
❷ key 存储有序问题,OrderPreservingPartitioner;
❸ 是条带数据散布的须要,Keyspace 级别的 Partitioner 设定。
前面说 key 存储用到了 OrderPreservingPartitioner,这样在一套系统里须要两套不一样的 partition 机制,若是进行数据交互,就须要既要保持 RandomPartition 的结构,还要保持 OrderPreservingPartitioner 的结构。这样的话,数据交换会变的异常的复杂,因此作了一个消息传递,过程当中仍是使用 LongToken 去存,在使用时,仍是须要维护两套,当撤出或者加入环中时,都要进行转化,因此系统会看到两套内容。

file

其余的改进点以下:

❶ Hinted handoff :外部工具,解决宕机时间过长,超过 Hinted 时间窗口;

❷ MemTable Flush 选盘策略:避免并发 dump MemTable 带来的 CPU 开销,避免小文件的产生;

❸ Cassandra 集群管控,配置自动加载,磁盘自动下线报修。

PS: DataFunTalk NLP交流群,跟同行零距离交流。如想进群,请加逃课儿同窗的微信 ( 微信号:DataFunTalker ),回复:NLP,逃课儿会自动拉你进群。

相关文章
相关标签/搜索