【分布式系统】3.分布式系统基础设施之缓存与持久化存储

1.分布式系统的基础设施

       一个大型的稳健成熟的分布式系统的背后,往往会涉及众多的支撑系统,我们将这些支撑系统称为分布式系统的基础设施。除了前面所介绍的分布式协作及配置管理系统zookeeper之外,我们进行系统架构设计所依赖的基础设施,还包括分布式缓存系统持久化存储分布式消息系统搜索引擎,以及CDN系统负载均衡系统运维自动化系统等等,还有后面章节所要介绍的实时计算系统、离线计算系统、分布式文件系统、日志收集系统、监控系统、数据仓库等等。

2.分布式缓存

       高并发环境下,大量的读写请求涌向数据库,磁盘的处理速度内存显然不在一个量级,从减轻数据库的压力提高系统响应速度两个角度来考虑,一般都会在数据库之前加一层缓存。由于单台机器的内存资源以及承载能力有限,并且,如果大量使用本地缓存,也会使相同的数据被不同的节点存储多份,对内存资源造成较大的浪费,因此,才催生出了分布式缓存。

2.1 memcache

       memcache是一款开源的高性能的分布式内存对象缓存系统,用于在应用中减少对数据库的访问,提高应用的访问速度,并降低数据库的负载。
       为了在内存中提供数据的高速查找能力,memcache使用key-value的形式存储和访问数据,在内存中维护一张巨大的HashTable,使得对数据查询的时间复杂度降低到0(1),保证了对数据的高性能访问。内存的空间总是有限的,当内存没有更多的空间来存储新的数据时,memcache就会使用LRU(Least Recently Used)算法,将最近不常访问的数据淘汰掉,以腾出空间来存放新的数据。
       memcache存储支持的数据格式也是灵活多样的,通过对象的序列化机制,可以将更高层抽象的对象转换成为二进制数据,存储在缓存服务器中,当前端应用需要时,又可以通过二进制内容反序列化,将数据还原成原有对象。

2.2 缓存的分布式架构

        memcache本身并不是一种分布式的缓存系统,它的分布式,是由访问它的客户端来实现的。一种比较简单的实现方式是根据缓存的key来进行hash,当后端有N台缓存服务器时,访问的服务器为hash(key)%N,这样可以将前端的请求均衡的映射到后端的缓存服务器,如图所示,但是,这样也会导致一个问题,一旦后端某台缓存服务器宕机,或者是由于集群压力过大,需要新增新的缓存服务器,大部分的key将会重新分布,对于高并发系统来说,这可能会演变成一场灾难,所有的请求将如洪水般疯狂的涌向后端的数据库服务器,而数据库服务器的不可用,将会导致整个应用的不可用,形成所谓的“雪崩效应”

2.3 一致性hash算法

        consistent hash算法能够在一定程度上改善缓存的雪崩问题,它能够在移除/添加一台缓存服务器时,尽可能小的改变已存在的key映射关系,避免大量key的重新映射。

2.4 分布式session

        传统的应用服务器,如tomcat、jboss等等,其自身所实现的session管理大部分都是基于单机的,对于大型分布式网站来说,支撑其业务的远远不止是一台服务器,而是一个分布式集群,请求在不同服务器之间跳转,需要保持服务器之间的session同步。传统网站一般通过将一部分数据存储在cookie中,来规避分布式环境下session的操作,这样做弊端很多,一方面cookie的安全性一直广为诟病,并且,cookie存储数据的大小是有限制的,随着移动互联网的发展,很多情况下还得兼顾移动端的session需求,使得采用cookie来进行session同步的方式弊端更为凸显。分布式session正是在这种情况下应运而生的。

2.5 一种分布式session解决方案

        前端用户请求经过随机分发之后,可能会命中后端任意的web server,并且,web server也可能会因为各种不确定的原因宕机,这种情况下,session是很难在集群间同步的,而通过将session以sessionid作为key,保存到后端的缓存集群中,使得不管请求如何分配,即便是web server宕机,也不会影响其他的web server通过sessionid从cache server中获得session,这样,即实现了集群间的session同步,又提高了web server的容错性

2.6 缓存的容灾

     业务强依赖缓存,缓存需做到容灾
      1.双机房互相备份
      2.数据复制多份,单台缓存失效,集群间能够自动复制和备份
      3.数据库留有余量
      4.万兆网卡

2.7 持久化存储

        传统的IOE解决方案,使用和扩展的成本越来越高,使得互联网企业不得不思考新的解决方案,开源软件加廉价PC server的分布式架构,得益于社区的支持,在节约成本的同时,也给系统带来了良好的扩展能力,并且,由于开源软件的代码透明,使得企业能够以更低的代价定制更符合自身使用场景的功能,以提高系统的整体性能。互联网企业常用的三种数据存储方案,传统关系型数据库mysq1,用来存储结构化数据,google率先提出的bigtable概念及其开源实现HBase,则用来存储海量的非结构化数据,还有诸如包含丰富数据类型的key-value存储redis,文档型存储mongodb等等..

3.mysql

3.1 关系数据库mysql-业务拆分

         业务发展初期为了便于快速迭代,很多应用都采用集中式的架构,随着业务规模的扩展,系统变得越来越复杂,访问量越来越大,不得不进一步扩展系统的吞吐能力。举例来说,假设某门户网站,它包含了新闻、用户、帖子、评论等等几大块内容,对于数据库来说,它可能包含这样几张表,news、users、post、comment,随着数据量的增加,可以根据业务逻辑进行拆分,分成多个库,以提高系统吞吐能力

3.2 关系数据库mysql-数据复制

        通过数据库的复制策略,可以将一台mysq1数据库服务器中的数据复制到其他的mysq1数据库服务器之上,当各台数据库服务器上都包含相同数据的时候,前端应用通过访问mysq1集群中任意一台服务器,都能够读取到相同的数据,这样,每台mysq1服务器所需要承担的负载就会大大降低,从而提高整个系统的承载能力,达到系统扩展的目的。
        要实现数据库的复制,需要开启master服务器端的binary log,数据复制的过程实际上就是slave从master获取binary 1og,然后再在本地镜像的执行日志中所记录的操作,由于复制过程是异步的,因此,master和slave之间的数据有可能存在延迟的现象,此时只能够保证数据最终的一致性。

3.3 关系数据库mysql-读写分离

       前端服务器通过master来执行数据写入的操作,数据的更新通过binary log同步到slave集群,而对于数据读取的请求,则交由slave来处理,这样,slave集群可以分担数据库读的压力,并且,读写分离还保障了数据能够达到最终一致性。一般而言,大多数站点的读数据库操作要比写数据库操作更为密集,如果读的压力较大,还可以通过新增slave来进行系统的扩展,因此,master-slave的架构能够显著的减轻前面所提到的单库读的压力,毕竟在大多数应用当中,读的压力要比写的压力大的多。

3.4 关系数据库mysql-dual-master架构

       master-slaves复制架构存在一个问题,即所谓的单点故障,当master宕机,系统将无法写入,而在某些特定的场景下,可能需要master停机,以便进行系统维护、优化或者升级,同样的道理,master停机将导致整个系统都无法写入,直到master恢复,大部分情况下这显然是难以接受的。为了尽可能的降低系统停止写入的时间,最佳的方式就是采用dual master架构,即master-master架构

3.5 关系数据库mysql-分表

      对于访问极为频繁且数据量巨大的单表来说,我们首先要做的,就是减少单表的记录条数,以便减少数据查询所需要的时间,提高数据库的吞吐,这就是所谓的分表。在分表之前,首先需要选择适当的分表策略,使得数据能够较为均衡的分布到多张表中,并且,不影响正常的查询。
      对于互联网企业来说,大部分数据都是与用户进行关联的,因此,用户id是最常用的分表字段,因为大部分查询都需要带上用户id,这样既不影响查询,又能够使数据较为均衡的分布到各个表中。

3.6 关系数据库mysql-分库

       分表能够解决单表数据量过大带来的查询效率下降的问题,但是,却无法给数据库的并发处理能力带来质的提升,面对高并发的读写访问,当数据库master服务器无法承载写操作压力时,不管如何扩展slave服务器,此时都没有意义了。因此,我们必须换一种思路,对数据库进行拆分,从而提高数据库写入能力,这就是所谓的分库。

3.7 关系数据库mysql-分库分表

3.8 关系数据库mysql-分库分表策略

3.9 分库分表带来的限制

1.条件查询、分页查询受到限制,查询必须带上分库分表所带上的id
2.事务可能跨多个库,数据一致性无法通过本地事务实现,无法使用外键
3.分库分表规则确定以后,扩展变更规则需要迁移数据

3.10 为提升性能 mysql的取舍

    1.主从同步,master与slave之间数据存在延时同步,一致性由强一致性变为最终一致性
    2.分库分表,牺牲了查询的灵活性,必须带上分库分表所依赖的关键属性,牺牲了诸如外键、多表关联查询等RDBMS的传统特性.
     3.系统扩展复杂,数据库库、表路由规则的变更,数据迁移的成本高.4.业务拆分后,原先一个库中的表,可能被拆分到多个库中,使得原本简单的事务控制发展为分布式事务.

4.持久化存储--HBase

     HBase是Apache Hadoop项目下的一个子项目,它以google BigTable为原型,设计实现了高可靠性、高可扩展性、实时读写的列存储数据库,它的本质实际上是一张稀疏的大表,用来存储粗粒度的结构化数据,并且,能够通过简单的增加节点来实现系统的线性扩展。HBase运行在分布式文件系统HDFS之上,利用它可以在廉价的PC Server上搭建起大规模结构化存储集群。HBase的数据以表的形式来进行组织,每个表由行列组成,与传统的关系型数据库不同的是,HBase每个列属于一个特定的列族,通过行和列来确定一个存储单元,而每个存储单元又可以有多个版本,通过时间戳来标识。

4.1 持久化存储-hbase的架构

      HBase集群中通常包含两种角色,HMasterHRegionServer,当表随着记录条数的增加而不断变大后,将会分裂成一个个region,每个region可以由[startkey,endkey)来表示,它包含一个startkey到endkey的半闭区间。一个HRegionServer可以管理多个region,并由HMaster来负责HRegionServer的调度以及集群状态的监管。由于region可分散由不同的HRegionServer来管理,因此理论上再大的表都可以通过集群来处理。

4.2 持久化存储-hbase的使用场景和限制

         与传统的关系型数据库相比,HBase有更好的伸缩能力,更适合于海量数据的存储和处理,并且,由于多个region server的存在,使得HBase能够多个节点同时写入,显著提高了写入性能,并且是可扩展的。但是,HBase本身能够支持的查询维度有限,难以支持复杂查询,如group by、order by、join等等,这些特点使得它的应用场景受到了限制。当然,这也并非是不可弥补的硬伤,通过后面章节所介绍的搜索引擎,构建索引,可以在一定程度上解决HBase复杂条件组合查询的问题。

5.持久话存储-redis

          redis是一个高性能的key-value数据库,与其他很多key-value数据库不同之处在于,redis不仅支持简单的键值对类型的存储,它还支持其他的一系列丰富的数据存储结构,包括strings、hashs、lists、sets、sorted sets等等,并在这些数据结构类型上定义了一套强大的API。通过定义不同的存储结构,redis可以很轻易完成很多其他key-value数据难以完成的任务,如排序、去重等等。

1.使用场景

         相较于传统的关系型数据库,redis有更好的读写吞吐能力,能够支撑更高的并发数,而相较于其他的key-value类型的数据库,redis能够提供更为丰富的数据类型的支持,能够更灵活的满足业务需求。redis能够高效率的实现诸如排序取topN、访问计数器、队列系统、数据排重等等业务需求,并且,通过将服务器设置为cache-only,还能够提供高性能的缓存服务,相较于memcache来说,在性能差别不大的情况下,它能够支持更为丰富的数据类型。

发布了264 篇原创文章 · 获赞 347 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/jia970426/article/details/104996900