数据库存储大致分为如下几类,有关系型(事务型)的数据库,以oracle、mysql为表明,有keyvalue数据库,以redis和memcached db为表明,有文档型数据库如mongodb,有列式分布式数据库以HBase,cassandra,dynamo为表明,还有其余的图形数据库、对象数据 库、xml数据库等。每种类型的数据库应用的业务领域是不同的,下面从内存型、关系型、分布式三个维度针对相关的产品作性能可用性等方面的考量分析。node
内存型的数据库,以高并发高性能为目标,在事务性方面没那么严格,以开源nosql数据库mongodb、redis为例mysql
Ø Mongodbreact
通讯方式web
多线程方式,主线程监听新的链接,链接后,启动新的线程作数据的操做(IO切换)。redis
数据结构算法
数据库-->collection-->recordsql
MongoDB在数据存储上按命名空间来划分,一个collection是一个命名空间,一个索引也是一个命名空间。mongodb
同一个命名空间的数据被分红不少个Extent,Extent之间使用双向链表链接。数据库
在每个Extent中,保存了具体每一行的数据,这些数据也是经过双向连接链接的。浏览器
每一行数据存储空间不只包括数据占用空间,还可能包含一部分附加空间,这使得在数据update变大后能够不移动位置。
索引以BTree结构实现。
若是你开启了jorunaling日志,那么还会有一些文件存储着你全部的操做记录。
持久化存储
MMap方式把文件地址映射到内存的地址空间,直接操做内存地址空间就能够操做文件,不用再调用write,read操做,性能比较高。
mongodb调用mmap把磁盘中的数据映射到内存中的,因此必须有一个机制时刻的刷数据到硬盘才能保证可靠性,多久刷一次是与syncdelay参数相关的。
journal(进行恢复用)是Mongodb中的redo log,而Oplog则是负责复制的binlog。若是打开journal,那么即便断电也只会丢失100ms的数据,这对大多数应用来讲均可以容忍了。从1.9.2+,mongodb都会默认打开journal功能,以确保数据安全。并且journal的刷新时间是能够改变的,2-300ms的范围,使用 --journalCommitInterval 命令。Oplog和数据刷新到磁盘的时间是60s,对于复制来讲,不用等到oplog刷新磁盘,在内存中就能够直接复制到Sencondary节点。
事务支持
Mongodb只支持对单行记录的原子操做
HA集群
用的比较多的是Replica Sets,采用选举算法,自动进行leader选举,在保证可用性的同时,能够作到强一致性要求。
固然对于大量的数据,mongodb也提供了数据的切分架构Sharding。
Ø Redis
丰富的数据结构,高速的响应速度,内存操做
通讯方式
因都在内存操做,因此逻辑的操做很是快,减小了CPU的切换开销,因此为单线程的模式(逻辑处理线程和主线程是一个)。
reactor模式,实现本身的多路复用NIO机制(epoll,select,kqueue等)
单线程处理多任务
数据结构
hash+bucket结构,当链表的长度过长时,会采起迁移的措施(扩展原来两倍的hash表,把数据迁移过去,expand+rehash)
持久化存储
a、全量持久化RDB(遍历redisDB,读取bucket中的key,value),save命令阻塞主线程,bgsave开启子进程进行snapshot持久化操做,生成rdb文件。
在shutdown时,会调用save操做
数据发生变化,在多少秒内触发一次bgsave
sync,master接受slave发出来的命令
b、增量持久化(aof相似redolog),先写到日志buffer,再flush到日志文件中(flush的策略能够配置的,而已单条,也能够批量),只有flush到文件上的,才真正返回客户端。
要定时对aof文件和rdb文件作合并操做(在快照过程当中,变化的数据先写到aof buf中等子进程完成快照<内存snapshot>后,再进行合并aofbuf变化的部分以及全镜像数据)。
在高并发访问模式下,RDB模式使服务的性能指标出现明显的抖动,aof在性能开销上比RDB好,可是恢复时从新加载到内存的时间和数据量成正比。
集群HA
通用的解决方案是主从备份切换,采用HA软件,使得失效的主redis能够快速的切换到从redis上。主从数据的同步采用复制机制,该场景能够作读写分离。
目前在复制方面,存在的一个问题是在遇到网络不稳定的状况下,Slave和Master断开(包括闪断)会致使Master须要将内存中的数据所有从新生成rdb文件(快照文件),而后传输给Slave。Slave接收完Master传递过来的rdb文件之后会将自身的内存清空,把rdb文件从新加载到内存中。这种方式效率比较低下,在后面的将来版本Redis2.8做者已经实现了部分复制的功能。
关系型数据库在知足并发性能的同时,也须要知足事务性,以mysql数据库为例,讲述架构设计原理,在性能方面的考虑,以及如何知足可用性的需求。
Ø mysql的架构原理(innodb)
在架构上,mysql分为server层和存储引擎层。
Server层的架构对于不一样的存储引擎来说都是同样的,包括链接/线程处理、查询处理(parser、optimizer)以及其余系统任务。存储引擎层有不少种,mysql提供了存储引擎的插件式结构,支持多种存储引擎,用的最普遍的是innodb和myisamin;inodb主要面向OLTP方面的应用,支持事务处理,myisam不支持事务,表锁,对OLAP操做速度快。
如下主要针对innodb存储引擎作相关介绍。
在线程处理方面,Mysql是多线程的架构,由一个master线程,一个锁监控线程,一个错误监控线程,和多个IO线程组成。而且对一个链接会开启一个线程进行服务。io线程又分为节省随机IO的insert buffer,用于事务控制的相似于oracle的redo log,以及多个write,多个read的硬盘和内存交换的IO线程。
在内存分配方面,包括innodb buffer pool ,以及log buffer。其中innodb buffer pool包括insert buffer、datapage、index page、数据字典、自适应hash。Log buffer用于缓存事务日志,提供性能。
在数据结构方面,innodb包括表空间、段、区、页/块,行。索引结构是B+tree结构,包括二级索引和主键索引,二级索引的叶子节点是主键PK,根据主键索引的叶子节点指向存储的数据块。这种B+树存储结构能够更好的知足随机查询操做IO要求,分为数据页和二级索引页,修改二级索引页面涉及到随机操做,为了提升写入时的性能,采用insert buffer作顺序的写入,再由后台线程以必定频率将多个插入合并到二级索引页面。为了保证数据库的一致性(内存和硬盘数据文件),以及缩短实例恢复的时间,关系型数据库还有一个checkpoint的功能,用于把内存buffer中以前的脏页按照比例(老的LSN)写入磁盘,这样redolog文件的LSN之前的日志就能够被覆盖了,进行循环使用;在失效恢复时,只须要从日志中LSN点进行恢复便可。
在事务特性支持上,关系型数据库须要知足ACID四个特性,须要根据不一样的事务并发和数据可见性要求,定义了不一样的事务隔离级别,而且离不开对资源争用的锁机制,要避免产生死锁,mysql在Server层和存储引擎层作并发控制,主要体如今读写锁,根据锁粒度不一样,有各个级别的锁(表锁、行锁、页锁、MVCC);基于提升并发性能的考虑,使用多版本并发控制MVCC来支持事务的隔离,并基于undo来实现,在作事务回滚时,也会用到undo段。mysql 用redolog来保证数据的写入的性能和失效恢复,在修改数据时只须要修改内存,再把修改行为记录到事务日志中(顺序IO),不用每次将数据修改自己持久化到硬盘(随机IO),大大提升性能。
在可靠性方面,innodb存储引擎提供了两次写机制double writer用于防止在flush页面到存储上出现的错误,解决磁盘half-writern的问题。
Ø 对于高并发高性能的mysql来说,能够在多个维度进行性能方面的调优。
a、硬件级别,
日志和数据的存储,须要分开,日志是顺序的写,须要作raid1+0,而且用buffer-IO;数据是离散的读写,走direct IO便可,避免走文件系统cache带来的开销。
存储能力,SAS盘raid操做(raid卡缓存,关闭读cache,关闭磁盘cache,关闭预读,只用writeback buffer,不过须要考虑充放电的问题),固然若是数据规模不大,数据的存储能够用高速的设备,Fusion IO、SSD。
对于数据的写入,控制脏页刷新的频率,对于数据的读取,控制cache hit率;所以而估算系统须要的IOPS,评估须要的硬盘数量(fusion io上到IOPS 在10w以上,普通的硬盘150)。
Cpu方面,单实例关闭NUMA,mysql对多核的支持不是太好,能够对多实例进行CPU绑定。
b、操做系统级别,
内核以及socket的优化,网络优化bond、文件系统、IO调度
innodb主要用在OLTP类应用,通常都是IO密集型的应用,在提升IO能力的基础上,充分利用cache机制。须要考虑的内容有,
在保证系统可用内存的基础上,尽量的扩大innodb buffer pool,通常设置为物理内存的3/4
文件系统的使用,只在记录事务日志的时候用文件系统的cache;尽可能避免mysql用到swap(能够将vm.swappiness=0,内存紧张时,释放文件系统cache)
IO调度优化,减小没必要要的阻塞,下降随机IO访问的延时(CFQ、Deadline、NOOP)
c、server以及存储引擎级别(链接管理、网络管理、table管理、日志)
包括cache/buffer、Connection、IO
d、应用级别(好比索引的考虑,schema的优化适当冗余;优化sql查询致使的CPU问题和内存问题,减小锁的范围,减小回表扫描,覆盖索引)
Ø 在高可用实践方面,
支持master-master、master-slave模式,master-master模式是一个做为主负责读写,另一个做为standby提供灾备,maser-slave是一个做为主提供写操做,其余几个节点做为读操做,支持读写分离。
对于节点主备失效检测和切换,能够采用HA软件,固然也能够从更细粒度定制的角度,采用zookeeper做为集群的协调服务。
对于分布式的系统来说,数据库主备切换的一致性始终是一个问题,能够有如下几种方式:
a、集群方式,如oracle的rack,缺点是比较复杂
b、共享SAN存储方式,相关的数据文件和日志文件都放在共享存储上,优势是主备切换时数据保持一致,不会丢失,但因为备机有一段时间的拉起,会有短暂的不可用状态
c、主备进行数据同步的方式,常见的是日志的同步,能够保障热备,实时性好,可是切换时,可能有部分数据没有同步过来,带来了数据的一致性问题。能够在操做主数据库的同时,记录操做日志,切换到备时,会和操做日志作个check,补齐未同步过来的数据;
d、还有一种作法是备库切换到主库的regolog的存储上,保证数据不丢失。
数据库主从复制的效率在mysql上不是过高,主要缘由是事务是严格保持顺序的,索引mysql在复制方面包括日志IO和relog log两个过程都是单线程的串行操做,在数据复制优化方面,尽可能减小IO的影响。不过到了Mysql5.6版本,能够支持在不一样的库上的并行复制。
Ø 基于不一样业务要求的存取方式
平台业务中,不一样的业务有不一样的存取要求,好比典型的两大业务用户和订单,用户通常来说总量是可控的,而订单是不断地递增的,对于用户表首先采起分库切分,每一个sharding作一主多读,一样对于订单因更多需求的是用户查询本身的订单,也须要按照用户进行切分订单库,而且支持一主多读。
在硬件存储方面,对于事务日志因是顺序写,闪存的优点比硬盘高不了多少,因此采起电池保护的写缓存的raid卡存储;对于数据文件,不管是对用户或者订单都会存在大量的随机读写操做,固然加大内存是一个方面,另外能够采用高速的IO设备闪存,好比PCIe卡 fusion-io。使用闪存也适合在单线程的负载中,好比主从复制,能够对从节点配置fusion-IO卡,下降复制的延迟。
对于订单业务来说,量是不断递增的,PCIe卡存储容量比较有限,而且订单业务的热数据只有最近一段时间的(好比近3个月的),对此这里列两种解决方案,一种是flashcache方式,采用基于闪存和硬盘存储的开源混合存储方式,在闪存中存储热点的数据。另一种是能够按期把老的数据导出到分布式数据库HBase中,用户在查询订单列表是近期的数据从mysql中获取,老的数据能够从HBase中查询,固然须要HBase良好的rowkey设计以适应查询需求。
对 于数据的高并发的访问,传统的关系型数据库提供读写分离的方案,可是带来的确实数据的一致性问题提供的数据切分的方案;对于愈来愈多的海量数据,传统的数 据库采用的是分库分表,实现起来比较复杂,后期要不断的进行迁移维护;对于高可用和伸缩方面,传统数据采用的是主备、主从、多主的方案,可是自己扩展性比 较差,增长节点和宕机须要进行数据的迁移。对于以上提出的这些问题,分布式数据库HBase有一套完善的解决方案,适用于高并发海量数据存取的要求。
Ø HBase
基于列式的高效存储下降IO
一般的查询不须要一行的所有字段,大多数只须要几个字段
对与面向行的存储系统,每次查询都会所有数据取出,而后再从中选出须要的字段
面向列的存储系统能够单独查询某一列,从而大大下降IO
提升压缩效率
同列数据具备很高的类似性,会增长压缩效率
Hbase的不少特性,都是由列存储决定的
高性能
LSM Tree
适合高速写的场景
强一致的数据访问
MVCC
HBase的一致性数据访问是经过MVCC来实现的。
HBase在写数据的过程当中,须要通过好几个阶段,写HLog,写memstore,更新MVCC;
只有更新了MVCC,才算真正memstore写成功,其中事务的隔离须要有mvcc的来控制,好比读数据不能够获取别的线程还未提交的数据。
高可靠
HBase的数据存储基于HDFS,提供了冗余机制。
Region节点的宕机,对于内存中的数据还未flush到文件中,提供了可靠的恢复机制。
可伸缩,自动切分,迁移
经过Zookeeper定位目标Region Server,最后定位Region。
Region Server扩容,经过将自身发布到Master,Master均匀分布。
可用性
存在单点故障,Region Server宕机后,短期内该server维护的region没法访问,等待failover生效。
经过Master维护各Region Server健康情况和Region分布。
多个Master,Master宕机有zookeeper的paxos投票机制选取下一任Master。Master就算全宕机,也不影响Region读写。Master仅充当一个自动运维角色。
HDFS为分布式存储引擎,一备三,高可靠,0数据丢失。
HDFS的namenode是一个SPOF。
为避免单个region访问过于频繁,单机压力过大,提供了split机制
HBase的写入是LSM-TREE的架构方式,随着数据的append,HFile愈来愈多,HBase提供了HFile文件进行compact,对过时数据进行清除,提升查询的性能。
Schema free
HBase没有像关系型数据库那样的严格的schema,能够自由的增长和删除schema中的字段。
HBase分布式数据库,对于二级索引支持的不太好,目前只支持在rowkey上的索引,因此rowkey的设计对于查询的性能来说很是关键。
统一的配置库
部署平台
大型分布式系统涉及各类设备,好比网络交换机,普通PC机, 各类型号的网卡,硬盘,内存等等,还有应用业务层次的监控,数量很是多的时候,出现错误的几率也会变大,而且有些监控的时效性要求比较高,有些达到秒级 别;在大量的数据流中须要过滤异常的数据,有时候也对数据会进行上下文相关的复杂计算,进而决定是否须要告警。所以监控平台的性能、吞吐量、已经可用性就 比较重要,须要规划统一的一体化的监控平台对系统进行各个层次的监控。
平台的数据分类
应用业务级别:应用事件、业务日志、审计日志、请求日志、异常、请求业务metrics、性能度量
系统级别:CPU、内存、网络、IO
时效性要求
阀值,告警:
实时计算:
近实时分钟计算
按小时、天的离线分析
实时查询
架构
节点中Agent代理能够接收日志、应用的事件以及经过探针的方式采集数据,agent采集数据的一个原则是和业务应用的流程是异步隔离的,不影响交易流程。
数据统一经过collector集群进行收集,按照数据的不一样类型分发到不一样的计算集群进行处理;有些数据时效性不是那么高,好比按小时进行统计,放入hadoop集群;有些数据是请求流转的跟踪数据,须要能够查询的,那么就能够放入solr集群进行索引;有些数据须要进行实时计算的进而告警的,须要放到storm集群中进行处理。
数据通过计算集群处理后,结果存储到Mysql或者HBase中。
监控的web应用能够把监控的实时结果推送到浏览器中,也能够提供API供结果的展示和搜索。