大数据时代,企业对于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!互联网的发展伴随着技术概念的更新与相关功能的完善。而技术进步的背后,则是每一位技术人的持续的学习、周密的思考与不懈的尝试。

 

高并发大容量NoSQL解决方案探索的更多相关文章

  1. 企业高并发的成熟解决方案(一)video(笔记&知识点)

    知识点 答案 什么是高可用(HA) 高并发发生在哪两处 app服务器会出现什么问题,有哪些解决方案? 数据库并发有什么要求? hadoop集群的作用 负载均衡的功能有哪些 负载均衡的分类 哪种负载均衡 ...

  2. 企业高并发的成熟解决方案(一)----搭建LVS负载均衡

    企业整个架构分析 1. App服务器上边部署应用,如果是java的话,一般是tomcat: 2. 负载均衡服务器负责转发请求,这种既有主机又有备机的负载均衡成为高可用(HA): 3. 一般web服务器 ...

  3. Web网站高并发量的解决方案

    摘要:   一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单.随着互联网业务的不断丰富,网站相 ...

  4. 一个WEB网站高并发量的解决方案

    一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单.随着互联网业务的不断丰富,网站相关的技术经过 ...

  5. 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)

    问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...

  6. 转载:【高并发简单解决方案 | 靠谱崔小拽 】redis队列缓存 + mysql 批量入库 + php离线整合

    需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框 ...

  7. 【高并发简单解决方案】redis队列缓存 + mysql 批量入库 + php离线整合

    需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框 ...

  8. 【高并发简单解决方案】redis缓存队列+mysql 批量入库+php离线整合

    原文出处: 崔小拽 需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化 ...

  9. Web性能优化 高并发网站解决 单例 已看1

    Web性能优化分为服务器端和浏览器端两个方面. 一.浏览器端,关于浏览器端优化,分很多个方面1.压缩源码和图片JavaScript文件源代码可以采用混淆压缩的方式,CSS文件源代码进行普通压缩,JPG ...

随机推荐

  1. Tree - Gradient Boosting Machine with sklearn source code

    This is the second post in Boosting algorithm. In the previous post, we go through the earliest Boos ...

  2. Python中import的as语法

    在Python中,如果import的语句比较长,导致后续引用不方便,可以使用as语法,比如: import dir1.dir2.mod # 那么,后续对mod的引用,都必须是dir1.dir2.mod ...

  3. HUST学期助教总结

    春节还没过完,在回广州的高铁上收到是否愿意担任一次软测助教的询问.想了一天,答应了.而内心其实是有点恐慌的,有几点原因: 大学从来没有学过软件测试这门课程.对于自己的软件测试只是体系并不是很有自信. ...

  4. [数位DP]把枚举变成递推(未完)

    动态规划(DP)是个很玄学的东西 数位DP实际上 就是把数字上的枚举变成按位的递推 有伪代码 for i =这一位起始值 i<=这一位终止值 dp[这一位][i]+=dp[这一位-1][i]+- ...

  5. lintcode-65-两个排序数组的中位数

    65-两个排序数组的中位数 两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n)). 样例 给出数组A = [1,2,3,4,5,6] B = [ ...

  6. C#高级编程 (第六版) 学习 第五章:数组

    第五章 数组 1,简单数组 声明:int[] myArray; 初始化:myArray = new int[4]; 为数组分配内存. 还可以用如下的方法: int[] myArray = new in ...

  7. winform 弹出窗体指定位置

    在启动一个程序时,我们希望窗口显示的位置处于屏幕的正中心,可以如下设置: MainForm mainForm = new MainForm(); mainForm.StartPosition = Fo ...

  8. 【第三周】每周psp

    代码累计 300+575+475=1250 随笔字数 1700+3000+3785=8485 知识点 Cppunit框架 Ui设计 Scrum站立会议 燃尽图(好像没燃起来) 博客写作技能 本周主要是 ...

  9. java 两个数组合并

    需求:两个字符串合并(如果想去重复,参考下一篇--数组去重复及记录重复个数) //方法一 Arrays类 String[] a = {"A","B"," ...

  10. HTTP协议 结构,get post 区别(阿里面试)

    如果需要想了解相关的TCP的协议结构,底层架构,以及每次面试必问的三次握手,四次挥手可以 参考:TCP协议详解7层和4层解析(美团面试,阿里面试) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌 ...