数据库 高并发大容量 NoSQL 解决方案探索

HongJack · 2018年05月14日 · 最后由 tcstory 回复于 2018年05月15日 · 4408 次阅读

大数据时代,企业对于 DBA 也提出更高的需求。同时,NoSQL 作为近几年新崛起的一门技术,也受到越来越多的关注。本文将基于个推 SRA 孟显耀先生所负责的 DBA 工作,和大数据运维相关经验,分享两大方向内容:一、公司在 KV 存储上的架构演进以及运维需要解决的问题;二、对 NoSQL 如何选型以及未来发展的一些思考。

据官方统计,截止目前(2018年4月20日)NoSQL 有 225 个解决方案,具体到每个公司,使用的都是其中很小的一个子集,下图中蓝色标注的产品是当前个推正在使用的。

NoSQL 的由来

1946 年,第一台通用计算机诞生。但一直到 1970 年 RDMBS 的出现,大家才找到通用的数据存储方案。到 21 世纪,DT 时代让数据容量成为最棘手的问题,对此谷歌和亚马逊分别提出了自己的 NoSQL 解决方案,比如谷歌于 2006 年提出了 Bigtable。2009 年的一次技术大会上,NoSQL 一词被正式提出,到现在共有 225 种解决方案。

NoSQL 与 RDMBS 的区别主要在两点:第一,它提供了无模式的灵活性,支持很灵活的模式变更;第二,可伸缩性,原生的 RDBMS 只适用于单机和小集群。而 NoSQL 一开始就是分布式的,解决了读写和容量扩展性问题。以上两点,也是 NoSQL 产生的根本原因。

实现分布式主要有两种手段:副本(Replication)和分片(Sharding)。Replication 能解决读的扩展性问题和 HA(高可用),但是无法解决读和容量的扩展性。而 Sharding 可以解决读写和容量的扩展性。一般 NoSQL 解决方案都是将二者组合起来。

Sharding 主要解决数据的划分问题,主要有基于区间划分(如 Hbase 的 Rowkey 划分)和基于哈希的划分。为了解决哈希分布式的单调性和平衡性问题,目前业内主要使用虚拟节点。后文所述的 Codis 也是用虚拟节点。虚拟节点相当于在数据分片和托管服务器之间建立了一层虚拟映射的关系。

目前,大家主要根据数据模型和访问方式进行 NoSQL 分类。

个推常用的几种 NoSQL 解决方案

个推 Redis 系统规模如下图。下面介绍一下运维过程遇到的几个问题。

首先是技术架构演进过程。个推以面向 APP 开发者提供消息推送服务起家,在 2012 年之前,个推的业务量相对较小,当时我们用 Redis 做缓存,用 MySQL 做持久化。在 2012-2016 年,随着个推业务的高速发展,单节点已经无法解决问题。在 MySQL 无法解决高 QPS、TPS 的情况下,我们自研了 Redis 分片方案。此外,我们还自研了 Redis 客户端,用它来实现基本的集群功能,支持自定义读写比例,同时对故障节点的监测和隔离、慢监控以及每个节点健康性进行检查。但这种架构没有过多考虑运维效率的问题,缺少运维工具。

当我们计划完善运维工具的时候,发现豌豆荚团队将 Codis 开源,给我们提供了一个不错的选项。

个推 Codis+ 的优势

Codis 是 proxy-based 架构,支持原生客户端,支持基于 web 的集群操作和监控,并且也集成了 Redis Sentinel。可以提高我们运维的工作效率,且 HA 也更容易落地。

但是在使用过程中,我们也发现一些局限。因此我们提出了 Codis+,即对 Codis 做一些功能增强。

第一、 采用 2N+1 副本方案,解决故障期间 Master 单点的问题。

第二、Redis 准半同步。设置一个阈值,比如 slave 仅在 5 秒钟之内可读。

第三、资源池化。能通过类似 HBase 增加 RegionServer 的方式去进行资源扩容。

此外,还有机架感知功能和跨 IDC 的功能。Redis 本身是为了单机房而设置的,没有考虑到这些问题。

那么,为什么我们不用原生的 rRedis cluster?这里有三个原因:一、原生的集群,它把路由转发的功能和实际上的数据管理功能耦合在一个功能里,如果一个功能出问题就会导致数据有问题;二、在大集群时,P2P 的架构达到一致性状态的过程比较耗时,codis 是树型架构,不存在这个问题。三、集群没有经过大平台的背书。

此外,关于 Redis,我们最近还在看一个新的 NoSQL 方案 Aerospike,我们对它的定位是替换部分集群 Redis。Redis 的问题在于数据常驻内存,成本很高。我们期望利用 Aerospike 减少 TCO 成本。Aerospike 有如下特性:

一、Aerospike 数据可以放内存,也可以放 SSD,并对 SSD 做了优化。

二、资源池化,运维成本继续降低。

三、支持机架感知和跨 IDC 的同步,但这属于企业级版本功能。

目前我们内部现在有两个业务在使用 Aerospike,实测下来,发现单台物理机搭载单块 Inter SSD 4600,可以达到接近 10w 的 QPS。对于容量较大,但 QPS 要求不高的业务,可以选择 Aerospike 方案节省 TCO。

在 NoSQL 演进的过程中,我们也遇到一些运维方面的问题。

标准化安装

我们共分了三个部分:OS 标准化、Redis 文件和目录标准、Redis 参数标准化,全部用 saltstack + cmdb 实现;

扩容和缩容

在技术架构不断演进过程中,扩容和缩容的难度也在变低,原因之一在于 codis 缓解了一部分问题。当然,如果选择 Aerospike,相关操作就会非常轻松。

做好监控,降低运维成本

大部分的运维同学都应该认真阅读《SRE:Google 运维揭秘》,它在理论层面和实践层面提出了很多非常有价值的方法论,强烈推荐。

个推 Redis 监控复杂性

三种集群架构:自研、codis2 和 codis3,这三种架构采集数据的方式并不相同。

三类监控对象:集群、实例、主机,需要有元数据维护逻辑关系,并在全局做聚合。

三种个性化配置:个推的 Redis 集群,有的集群需要有多副本,有的不需要。有的节点允许满做缓存,有的节点不允许满。还有持久化策略,有的不做持久化,有的做持久化,有的做持久化 + 异地备份,这些业务特点对我们监控灵活性提出很高的要求。

Zabbix 是一个非常完备的监控系统,约三年多的时间里,我都把它作为主要的监控系统平台。但是它有两个缺陷:一是它使用 MySQL 作为后端存储,TPS 有上限;二是不够灵活。比如:一个集群放在一百台机器上,要做聚合指标,就很困难。

小米的 open-falcon 解决了这个问题,但是也会产生一些新问题。比如告警函数很少,不支持字符串,有时候会增加手工的操作等等。后来我们对它进行功能性补充,便没有遇到大的问题。

下图是个推运维平台。

第一个是 IT 硬件资源平台,主要维护主机维度的物理信息。比如说主机在哪个机架上接的哪个交换机,在哪个机房的哪一个楼层等等,这是做机架感知和跨 IDC 等等的基础。

第二个是 CMDB,这个是维护主机上的软件信息,主机上装了哪些实例,实例属于哪些集群,我们用了哪些端口,这些集群有什么个性化的参数配置,包括告警机制不一样,全是通过 CMDB 实现。CMDB 的数据消费方包含 grafana 监控系统和监控采集程序,采集程序由我们自己开发。这样 CMDB 数据会活起来。如果只是一个静态数据没有消费方,数据就会不一致。

grafana 监控系统聚合了多个 IDC 数据,我们运维每天只需看一下大屏就够了。

Slatstack,用于实现自动化发布,实现标准化并提高工作效率。

采集程序是我们自行研发的,针对公司的业务特点定制化程度很高。还有 ELK(不用 logstach,用 filebeat)做日志中心。

通过以上这些,我们搭建出个推整个监控体系。

下面讲一下搭建过程中遇到的几个坑。

一、主从重置,会导致主机节点压力爆增,主节点无法提供服务。

主从重置有很多原因。

Redis 版本低,主从重置的概率很高。Redis3 主从重置的概率比 Redis2 大大减少,Redis4 支持节点重启以后也能增量同步,这是 Redis 本身进行了很多改进。

我们现在主要使用的是 2.8.20,属于比较容易能产生主从重置。

Redis 的主从重置一般是触发了如下条件中的一个。

1、repl-backlog-size 太小,默认是 1M,如果你有大量的写入,很容易击穿这个缓冲区;2、repl-timeout,Redis 主从默认每十秒钟 ping 一次,60 秒钟 ping 不推就会主从重置,原因可能是网络抖动、总节点压力过大,无法响应这个包等;3、tcp-baklog,默认是 511。操作系统的默认是限制到 128,这个可以适度提高,我们提高到 2048,这个能对网络丢包现象进行一定容错。

以上都是导致主从重置的原因,主从重置的后果很严重。Master 压力爆增无法提供服务,业务就把这个节点定为不可用。响应时间变长 Master 所在所有主机的节点都会受到影响。

二、节点过大,部分是人为原因造成的。第一是拆分节点的效率较低,远远慢于公司业务量的增长。此外,分片太少。我们的分片是 500 个,codis 是 1024,codis 原生是 16384 个,分片太少也是个问题。如果做自研的分布式方案,大家一定要把分片数量,稍微设大一点,避免业务发展超过你预期的情况。节点过大之后,会导致持久化的时间增长。我们 30G 的节点要持久化,主机剩余内存要大于 30G,如果没有,你用 Swap 导致主机持久化时间大幅增长。一个 30G 的节点持久化可能要 4 个小时。负载过高也会导致主从重置,引起连锁反应。

关于我们遇到的坑,接下来分享几个实际的案例。

第一个案例是一次主从重置。这个情况是在春节前两天出现的,春节前属于消息推送业务高峰期。我们简单还原一下故障场景。首先是大规模的消息下发导致负载增加;然后,Redis Master 压力增大,TCP 包积压,OS 产生丢包现象,丢包把 Redis 主从 ping 的包给丢了,触发了 repl-timeout 60 秒的阈值,主从就重置了。同时由于节点过大,导致 Swap 和 IO 饱和度接近 100%。解决的方法很简单,我们先把主从断开。故障原因首先是参数不合理,大都是默认值,其次是节点过大让故障效果进行放大。

第二个案例是 codis 最近遇到的一个问题。这是一个典型的故障场景。一台主机挂掉后,codis 开启了主从切换,主从切换后业务没有受影响,但是我们去重新接主从时发现接不上,接不上就报了错。这个错也不难查,其实就是参数设置过小,也是由于默认值导致。Slave 从主节点拉数据的过程中,新增数据留在 Master 缓冲区,如果 Slave 还没拉完,Master 缓冲区就超过上限,就会导致主从重置,进入一个死循环。

基于这些案例,我们整理了一份最佳实践。

一、配置 CPU 亲和。Redis 是单机点的结构,不亲和会影响 CPU 的效率。

二、节点大小控制在 10G。

三、主机剩余内存最好大于最大节点大小 +10G。主从重置需要有同等大小的内存,这个一定要留够,如果不留够,用了 Swap,就很难重置成功。

四、尽量不要用 Swap。500 毫秒响应一个请求还不如挂掉。

五、tcp-backlog、repl-backlog-size、repl-timeout 适度增大。

六、Master 不做持久化,Slave 做 AOF+ 定时重置。

最后是个人的一些思考和建议。选择适合自己的 NoSQL,选择原则有五点:

1、业务逻辑。首先要了解自身业务特点,比如是 KV 型就在 KV 里面找;如果是图型就在图型里找,这样范围一下会减少 70%-80%。

2、负载特点,QPS、TPS 和响应时间。在选择 NoSQL 方案时,可以从这些指标去衡量,单机在一定配置下的性能指标能达到多少?Redis 在主机足够剩余情况下,单台的 QPS40-50 万是完全 OK 的。

3、数据规模。数据规模越大,需要考虑的问题就越多,选择性就越小。到了几百个 TB 或者 PB 级别,几乎没太多选择,就是 Hadoop 体系。

4、运维成本和可不可监控,能否方便地进行扩容、缩容。

5、其它。比如有没有成功案例,有没有完善的文档和社区,有没有官方或者企业支持。可以让别人把坑踩过之后我们平滑过去,毕竟自己踩坑的成本还是蛮高的。

结语:关于 NoSQL 的释义,网络上曾有一个段子:从 1980 年的 know SQL,到 2005 年的 Not only SQL,再到今日的 No SQL!互联网的发展伴随着技术概念的更新与相关功能的完善。而技术进步的背后,则是每一位技术人的持续的学习、周密的思考与不懈的尝试。

MySQL 或者 PG 到 PB 级别都没问题的啊, 无非就是集群而已

然后搭配一个时序性的就好, 例如 ClickHouse 了解一下

luikore 回复

俄国人厉害

“今日应该是 NewSQL 了”。 当然,不同数据库的在不同的使用场景发挥的优势是不同

不错的文章😏

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册