探索高并发大容量的NoSQL解决方案与此同时,NoSQL作为近几年新兴的技术,也越来越受到人们的关注。基于格推SRA孟先耀先生负责的DBA工作以及大数据运维的相关经验,本文将从两个方向分享内容:1、公司KV存储架构的演进及需要解决的问题在运维中解决;如何选择NoSQL以及对未来发展的一些思考。据官方统计,截至目前(2018年4月20日),共有225个NoSQL解决方案,每个公司都使用其中的一小部分。下图中蓝色标出的产品为当前产品。正在使用推送。NoSQL的起源1946年,第一台通用计算机诞生。但是直到1970年RDMBS的出现,大家才找到了通用的数据存储方案。21世纪,DT时代,数据容量成为最棘手的问题。Google和Amazon分别提出了自己的NoSQL解决方案。比如谷歌在2006年提出了Bigtable,在2009年的一次技术会议上,正式提出了NoSQL这个词,目前有225个解决方案。NoSQL和RDMBS的区别主要有两点:第一,它提供了无模式的灵活性,支持非常灵活的模式变化;第二,可扩展性,原生RDBMS只适用于单机和小型集群。NoSQL从一开始就是分布式的,解决了读写和容量扩展的问题。以上两点也是NoSQL产生的根本原因。实现分布的手段主要有两种:复制(Replication)和分片(Sharding)。Replication可以解决读和HA(高可用)的扩展性问题,但不能解决读和容量的扩展性问题。Sharding可以解决读写和容量的扩展性。一般的NoSQL解决方案是两者的结合。Sharding主要解决数据划分的问题,主要是基于区间划分(比如Hbase的Rowkey划分)和基于hash的划分。为了解决哈希分布的单调性和平衡性问题,目前业界主要采用虚拟节点。后文介绍的Codis也使用了虚拟节点。虚拟节点相当于在数据分片和托管服务器之间建立虚拟映射关系。目前我们主要按照数据模型和访问方式对NoSQL进行分类。几种常用的NoSQL方案和Redis系统的规模如下图所示。下面介绍运维过程中遇到的几个问题。首先是技术架构演进的过程。一个推开始为APP开发者提供消息推送服务。2012年之前,格推的业务量比较小。当时我们用Redis做缓存,用MySQL做持久化。2012年到2016年,随着推送业务的快速发展,单节点已经不能解决问题。在MySQL无法解决高QPS和TPS的情况下,我们自行开发了Redis分片方案。此外,我们还开发了Redis客户端,用它来实现集群的基本功能,支持自定义读写比例,以及监控和隔离故障节点,慢速监控,检查各个节点的健康度。但是这种架构并没有过多的考虑运维效率,缺乏运维工具。当我们打算完善运维工具的时候,发现豌豆荚团队把Codis开源了,给我们提供了一个很好的选择。Codis+的优点是Codis是基于代理的架构,支持原生客户端,支持基于web的集群运行和监控,还集成了RedisSentinel。可以提高我们运维的效率,HA也更容易实现。但是在使用的过程中,我们也发现了一些局限性。所以我们提出了Codis+,就是对Codis做一些功能上的增强。***,采用2N+1复制方案解决Master单点故障时的问题。第二,Redis是准半同步的。设置一个阈值,比如slave只能在5秒内可读。三是资源汇聚。可以通过类似HBase添加RegionServer的方式进行资源扩容。此外,还有机架感知功能和跨IDC功能。Redis本身是针对单机房设置的,没有考虑这些问题。那么,为什么我们不用原生的rRedis集群呢?这里有三个原因:1.原有的集群,将路由转发功能和实际的数据管理功能耦合为一个功能。如果某个功能失效,就会导致数据出现问题;2.在大型集群中,P2P架构达到一致状态的过程是耗时的。Codis是树形架构,所以不存在这个问题。3.集群没有被大平台背书。另外,关于Redis,我们最近还在看一个新的NoSQL解决方案Aerospike,我们对它的定位是替代部分集群Redis。Redis的问题是数据驻留在内存中,这很昂贵。我们希望通过Aerospike降低TCO成本。Aerospike具有以下特点:1.Aerospike数据可以存储在内存或SSD中,SSD已经过优化。2、资源汇集,运维成本持续下降。3、支持机架感知和跨IDC同步,不过这个是企业版功能。目前,我们的两个内部业务正在使用Aerospike。经过实测,我们发现单台物理机搭载单块InterSSD4600可以达到接近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)作为日志中心。通过以上,我们构建了一个完整的监控系统。说说在搭建过程中遇到的几个坑。1、主从重置会导致宿主节点压力爆发,主节点无法提供服务。主从重置的原因有很多。如果Redis版本低,主从重置的概率就高。Redis3主从重置的概率远低于Redis2。Redis4支持节点重启后的增量同步。这是因为Redis本身做了很多改进。我们现在主要用的是2.8.20,比较容易产生主从复位。Redis的主从重置一般会触发以下情况之一。1.repl-backlog-size太小,默认1M,如果写的很多,很容易冲破这个buffer;2、repl-timeout,Redis主从默认每十秒ping一次,60秒ping不通则主从重置。原因可能是网络抖动,总节点压力太大,无法响应这个数据包等;3.tcp-baklog,默认是511,操作系统默认限制是128,可以适度增加,我们增加到2048,可以容错网络丢包。以上都是主从复位的原因,主从复位的后果是非常严重的。Master的压力爆发,无法提供服务,所以业务让这个节点不可用。响应时间变长,Master所在的所有主机的节点都会受到影响。二是节点过大,部分是人为因素造成的。***是节点分裂效率低下,远远慢于公司业务量的增长。还有,碎片太少了。我们的shards是500,codis是1024,codis原生是16384,shards太少也是个问题。如果是做自研的分布式方案,一定要将分片数量设置的稍微大一些,避免出现业务发展超出预期的情况。节点太大后,持久化时间会增加。我们30G的节点需要持久化,宿主机剩余内存必须大于30G。否则,使用Swap会导致主机持久化时间显着增加。一个30G的节点持久化可能需要4个小时。过高的负载也会导致主从重置,引起连锁反应。关于我们遇到的坑,我分享几个实际案例。第一种情况是主从复位。这种情况发生在春节前两天,正是春节前新闻推送业务的高峰期。让我们简要还原故障场景。首先,大规模的消息传递导致负载增加;然后,RedisMaster压力增大,TCP包积压,OS产生丢包。丢包导致Redis主从ping包丢失,触发repl-timeout60秒阈值,主从复位。同时由于节点过多,Swap和IO的饱和度接近100%。解决方法很简单,我们先断开主从。失败的原因一是参数不合理,大部分是默认值,二是节点太大,放大了失败的影响。第二种情况是codis最近遇到的一个问题。这是一个典型的故障场景。一台主机挂掉后,codis启动主从切换。主从切换后,业务不受影响,但是当我们重新连接主从时,发现连接不上,连接不上就报错。这个错误不难发现。其实是参数设置太小,也是默认值造成的。Slave在从Master节点拉取数据的过程中,新加入的数据一直保留在Master的buffer中。如果Slave还没有拉完数据,Master的buffer就会超过上限,导致主从复位,进入死循环。基于这些案例,我们总结了一个最佳实践。1.配置CPU亲和性。Redis是一个独立的结构,不兼容会影响CPU的效率。2、节点大小控制在10G。3.主机剩余内存大于最大节点大小+10G。主从复位需要有相同大小的内存,这个一定要够,如果不够用Swap,很难复位成功。四、尽量不要使用Swap。500毫秒响应请求比挂断还糟糕。5.适度增加tcp-backlog、repl-backlog-size和repl-timeout。6、Master不做持久化,Slave做AOF+定时复位。***是个人的一些想法和建议。选择适合自己的NoSQL有五个原则:1、业务逻辑。首先,你必须了解自己的业务特点。比如是KV类型的,可以在KV里面找;2、负载特性、QPS、TPS和响应时间。在选择NoSQL方案时,可以从这些指标进行衡量。单机在一定配置下能达到多少性能指标?如果剩余主机足够多,Redis单台QPS40万-50万是完全可以的。3、数据规模。数据量越大,考虑的问题越多,选择性越低。在几百TB或者PB级别,几乎没有多少选择,那就是Hadoop系统。4、运维成本及是否可监控,是否可方便扩容或缩减。五、其他。比如有没有成功的案例,有没有完善的文档和社区,有没有官方或者企业的支持。让别人踩坑之后,我们就可以把它抹平了。毕竟踩坑的成本还是挺高的。结语:关于NoSQL的定义,网上流传着一个笑话:从1980年的KnowSQL,到2005年的NotonlySQL,再到今天的NoSQL!互联网的发展伴随着技术理念的更新和相关功能的完善。技术进步的背后,是每一位技术人的不断学习、细心思考和不懈尝试。
