系统架构与设计(3)- 如何设计高并发系统的数据库架构 (二)


在 WEB 网站的规模从小到大不断扩展的过程中,数据库的访问压力也不断的增加,数据库的架构也需要动态扩展,在数据库的扩展过程基本上包含如下几步,每一个扩展都可以比上一步骤的部署方式的性能得到数量级的提升。


1. 数据库架构的扩展

    1) WEB 应用和数据库部署在同一台服务器上

        一般的小规模的网站采用这种方式,用户量、数据量、并发访问量都比较小,否则单台服务器无法承受,并且在遇到性能瓶颈的时候升级硬件所需要的费用非常高昂,在访问量增加的时候,应用程序和数据库都来抢占有限的系统资源,很快就又会遇到性能问题。

    2) WEB 应用和数据库部署在各自独立的服务器上

        WEB 应用和数据库分开部署,WEB 应用服务器和数据库服务器各司其职,在系统访问量增加的时候可以分别升级应用服务器和数据库服务器,这种部署方式是一般小规模网站的典型部署方式。在将应用程序进行性能优化并且使用数据库对象缓存策略的情况下,可以承载较大的访问量,比如 2000 用户,200 个并发,百万级别的数据量。

    3) 数据库服务器采用集群方式部署(比如 Oracle 的一个数据库多个实例的情况)

        数据库集群方式能承担的负载是比较大的,数据库物理介质为一个磁盘阵列,多个数据库实例以虚拟IP方式向外部应用服务器提供数据库连接服务。这种部署方式基本上可以满足绝大多数的常见 WEB 应用,但是还是不能满足大用户量、高负载、数据库读写访问非常频繁的应用。

    4) 数据库采用主从部署方式

        在面向大众用户的博客、论谈、交友、CMS 等系统中,有上百万的用户,有上千万的数据量,存在众多的数据库查询操作,也有较多的数据库写操作,并且在多数情况下都是读操作远大于写操作的。在这个时候,假如能将数据库的读写操作分离的话,对于系统来讲是一个很大的提高啦。数据库的主从部署方式就走到我们面前啦。

        (1) 主从复制

            几乎所有的主流数据库都支持复制,这是进行数据库简单扩展的基本手段。下面以 MySQL 为例来说明,它支持主从复制,配置也并不复杂,只需要开启主服务器上的二进制日志以及在主服务器和从服务器上分别进行简单的配置和授权。
            
            MySQL 的主从复制是一句主服务器的二进制日志文件进行的,主服务器日志中记录的操作会在从服务器上重放,从而实现复制,所以主服务器必须开启二进制日志,自动记录所有对于主数据库的更新操作,从服务器再定时到主服务器取得二进制日志文件进行重放则完成了数据的复制。主从复制也用于自动备份。

        (2) 读写分离

            为保证数据库数据的一致性,我们要求所有对于数据库的更新操作都是针对主数据库的,但是读操作是可以针对从数据库来进行。大多数站点的数据库读操作比写操作更加密集,而且查询条件相对复杂,数据库的大部分性能消耗在查询操作上了。

            主从复制数据是异步完成的,这就导致主从数据库中的数据有一定的延迟,在读写分离的设计中必须要考虑这一点。以博客为例,用户登录后发表了一篇文章,他需要马上看到自己的文章,但是对于其它用户来讲可以允许延迟一段时间(1分钟/5分钟/30分钟),不会造成什么问题。这时对于当前用户就需要读主数据库,对于其他访问量更大的外部用户就可以读从数据库。

        (3) 数据库反向代理

            在读写分离的方式使用主从部署方式的数据库的时候,会遇到一个问题,一个主数据库对应多台从服务器,对于写操作是针对主数据库的,数据库个数是唯一的,但是对于从服务器的读操作就需要使用适当的算法来分配请求啦,尤其对于多个从服务器的配置不一样的时候甚至需要读操作按照权重来分配。

            对于上述问题可以使用数据库方向代理来实现。就像 Web 方向代理服务器一样,可以使用 Haproxy 或 Nginx 配置 MySQL 反向代理。

    5) 数据库垂直分割

        主从部署数据库中,当写操作占了主数据库的 CPU 消耗的 50% 以上的时候,我们再增加从服务器的意义就不是很大了,因为所有的从服务器的写操作也将占到 CPU 消耗的 50% 以上,一台从服务器提供出来查询的资源非常有限。数据库就需要重新架构了,我们需要采用数据库垂直分区技术。

        最简单的垂直分区方式是将原来的数据库中独立的业务进行分拆(被分拆出来的部分与其它部分不需要进行 Join 连接查询操作),比如 WEB 站点的 BLOG 和 论坛,是相对独立的,与其它的数据的关联性不是很强,这时可以将原来的的数据库拆分为一个 BLog 库,一个论坛库,以及剩余的表所组成的库。这三个库再各自进行主从数据库方式部署,这样整个数据库的压力就分担。

        另外查询扩展性也是采用数据库分区最主要的原因之一。将一个大的数据库分成多个小的数据库可以提高查询的性能,因为每个数据库分区拥有自己的一小部分数据。假设您想扫描1亿条记录,对一个单一分区的数据库来讲,该扫描操作需要数据库管理器独立扫描一亿条记录,如果您将数据库系统做成 50 个分区,并将这 1 亿条记录平均分配到这 50 个分区上,那么每个数据库分区的数据库管理器将只扫描 200 万记录。

    6) 数据库水平分割

        在数据库的垂直分区之后,假如我们的 BLOG 库又再次无法承担写操作的时候,我们又该怎么办呢?数据库垂直分区这种扩展方式又无能为力了,我们需要的是水平分区。

        水平分区意味着我们可以将同一个数据库表中的记录通过特定的算法进行分离,分别保存在不同的数据库表中,从而可以部署在不同的数据库服务器上。很多的大规模的站点基本上都是主从复制+垂直分区+水平分区这样的架构。水平分区并不依赖什么特定的技术,完全是逻辑层面的规划,需要的是经验和业务的细分。

        如何分区呢?对于大型的 WEB 站点来说,必须分区,并且对于分区我们没有选择的余地,对于那些频繁访问导致站点接近崩溃的热点数据,我们必须分区。

        在对数据分区的时候,我们必须要存在一个分区索引字段,比如 USER_ID,它必须和所有的记录都存在关系,是分区数据库中的核心表的主键,在其它表中作为外键,并且在使用主键的时候,该主键不能是自增长的,必须是业务主键才可以。

        (1) 余数分区

            我们可以将 User_ID%10 后的值为依据存入到不同的分区数据库中,该算法简单高效,但是在分区数据库个数有变动的时候,整个系统的数据需要重新分布。

        (2) 范围分区

            我们可以将 User_ID 的范围进行分区,比如 1-100000 范围为一个分区数据库,100001-200000范围为一个分区数据库,该算法在分区数据库个数有变动的时候,系统非常有利于扩展,但是容易导致不同分区之间的压力不同,比如老用户所在的分区数据库的压力很大,但是新用户的分区数据库的压力偏小。    

        (3) 映射关系分区   

            将对分区索引字段的每个可能的结果创建一个分区映射关系,这个映射关系非常庞大,需要将它们写入数据库中。比如当应用程序需要知道 User_id 为 10 的用户的 BLOG 内容在那个分区时,它必须查询数据库获取答案,当然,我们可以使用缓存来提高性能。

            这种方式详细保存了每一个记录的分区对应关系,所以各个分区有非常强的可伸缩性,可以灵活的控制,并且将数据库从一个分区迁移到另一个分区也很简单,也可以使各个分区通过灵活的动态调节来保持压力的分布平衡。

 


2. MySQL 官方的解决方案

    1) MySQL Replication

        MySQL Replication 是 MySQL 的一个非常重要的功能,主要用于主服务器和从服务器之间的数据复制操作。

        文档:https://dev.mysql.com/doc/refman/5.6/en/replication.html

        MySQL 复制是指从一个 MySQL 主服务器(master)将数据复制到另一台或者多台 MySQL 从服务器(slaves)的过程,将主数据库的 DDL 和 DML 操作通过二进制日志传递到复制服务器上,然后在服务器上对这些日志重新执行,从而使得主从服务器的数据保持同步;

        在 MySQL 中,复制操作时异步进行的,slaves 服务器不需要持续地保持连接接收 master 服务器的数据。

        MySQL 支持一台主服务器同时向多台从服务器进行复制操作,从服务器同时可以作为其他从服务器的主服务器,如果 MySQL 主服务器的访问量比较大,可以通过复制数据,然后在从服务器上进行查询操作,从而降低主服务器的访问压力,同时从服务器作为主服务器的备份,可以避免主服务器因为故障数据丢失的问题;

        MySQL 数据库复制操作大致可以分为三个步骤:

            (1) 主服务器将数据改变记录到二进制日志(binary log)中;
            (2) 从服务器将主服务器的 binary log events 复制到它的中继日志(relay log)中;
            (3) 从服务器重做中继日志中的事件,将数据的改变与从服务器保持同步;

        综合评价:

            能完成基础的主从复制,但 Replication 架构简单、功能相对单一。

    2) MySQL Fabirc

        Farbic 由 MySQL Replication 基础特性和一些扩展框架构建而成,用于管理 MySQL Servers Farms,与基本的 Replicaiton 相比,它实现了2个核心的特性:HA 和 sharding。Fabric 集群中任何时候只有一个 Primary (即 master),其他的实例为 Secondaries (即 slaves);通过使用 Replication,将数据在多个节点上备份,HA 总是保持集群的数据可用性。
        
        如下特性是 Replication 所不具备的:

            (1) 故障检测和角色迁移 (Failover):Fabric 进程用于监控集群中的所有节点,如果发现primary 失效,稍后他将从 Secondaries 中选择一个 “数据最新” 的节点,并提升为 primary;此后其他的 secondaries 将从新的 priamry 上同步数据变更操作。Connectors(比如 Connector/J 客户端)发现 primary 故障时也会通知 Fabirc,那么 Fabric 将通知信息作为决策的一部分来判定 priamry 的状态。这个特性简称为 “自动Failover”,是 Replication 架构中必备的手段之一。

            (2) 数据库请求路由 (Router):当 Fabric 提升一个新的 primary 后,它将会更新 state store (存储 Replication 的节点状态等),此后 Connectors 将会获取新的 state 数据并在客户端本地 cache。因此,application 不需要时刻关注(aware)集群中 servers 拓扑结构的变化,只需要根据 state cache 中的 server 状态,将 writes 发送给相应的 primary 即可。这种特性由 Connectors 客户端与 Fabric 共同实现,在普通的 Replication 架构中,客户端自动角色路由是无法完成的。如果 cache 中拓扑不是最新的,application 的操作异常将会反馈给Fabirc,参考 (1)。

        缺点及限制:
            
            (1) 自增长键不能作为分片的键;
            (2) 事务及查询只支持在同一个分片内,事务中更新的数据不能跨分片,查询语句返回的数据也不能跨分片。

        综合评价:

            Fabric 是 Replicaiton 模式的完善和补充,增加了自动 Failover 和 sharding 机制,以支撑更大规模的数据访问,减少人工干预;

    3) MySQL Cluster

        MySQL Cluster 是 MySQL 官方集群部署方案,支持通过自动分片支持读写扩展,通过实时备份冗余数据,是可用性最高的方案,声称可做到 99.999% 的可用性。

        文档:https://dev.mysql.com/doc/index-cluster.html

        MySQL Cluster 使用了一个插件式的存储引擎,与 MySQL 存储引擎 (InnoDB、MySAM) 架构有很大不同。

        MySQL Cluster 主要由三种类型的服务组成:

            (1) NDB Management Server:管理服务器主要用于管理 cluster 中的其他类型节点(Data Node 和 SQL Node),通过它可以配置 Node 信息,启动和停止 Node。
            (2) SQL Node:在 MySQL Cluster 中,一个 SQL Node 就是一个使用 NDB 引擎的 MySQL Server 进程,用于供外部应用提供集群数据的访问入口。
            (3) Data Node:用于存储集群数据;系统会尽量将数据放在内存中。

        缺点及限制:

            (1) 对需要进行分片的表需要修改引擎 Innodb 为 NDB,不需要分片的可以不修改。
            (2) NDB 的事务隔离级别只支持 Read Committed,即一个事务在提交前,查询不到在事务内所做的修改;而 Innodb 支持所有的事务隔离级别,默认使用 Repeatable Read,不存在这个问题。
            (3) 外键支持:虽然最新的 Cluster 版本已经支持外键,但性能有问题(因为外键所关联的记录可能在别的分片节点中),所以建议去掉所有外键。
            (4) Data Node 节点数据会被尽量放在内存中,对内存要求大。

        提供了四种事务隔离级别:
        
            (1) Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
            (2) Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。
            (3) Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
            (4) Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。

        综合评价:
        
            Cluster 是一个全分布式架构,是面向大规模数据存储的解决方案。


    4) MySQL GTID Replication

        从 MySQL 5.6 开始增加了强大的 GTID(Global Transaction ID,全局事务ID)这个特性,用来强化数据库的主备一致性, 故障恢复, 以及容错能力。用于取代过去传统的主从复制(即:基于 binlog和 position 的异步复制)。借助 GTID,在发生主备切换的情况下,MySQL 的其他 slave 可以自动在新主上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制position 发生误操作的风险。另外,基于 GTID 的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。

        文档:https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html

        GTID 是由 server_uuid 和事务 id 组成的,即 GTID=server_uuid:transaction_id。

            (1) server_uuid:是在 MySQL 第一次启动时自动生成并持久化到 auto.cnf 文件(存放在数据目录下,每台机器的 server_uuid 都不一样。
            (2) transaction_id:是一个从 1 开始的自增计数,表示在这个主库上执行的第 n 个事务。MySQL 会保证事务与 GTID 之间的 1:1 映射,如:6ba9a76d-606b-11ea-b3ce-000c29cb3421:1 表示在以 6ba9a76d-606b-11ea-b3ce-000c29cb3421 为唯一标识的 MySQL 实例上执行的第 1 个数据库事务。
            (3) 一组连续的事务可以用 “-” 连接的事务序号范围表示。例如:6ba9a76d-606b-11ea-b3ce-000c29cb3421:1-15

        GTID Replication 优点:

            (1) 更简单的实现 failover,不用以前那样在需要找 log_file 和 log_Pos;
            (2) 更简单的搭建主从复制;
            (3) 比传统复制更加安全;
            (4) GTID 是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。

        GTID Replication 的工作原理:

            (1) 主节点更新数据时,会在事务前产生 GTID,一起记录到 binlog 日志中;
            (2) 从节点的 I/O 线程将变更的 bin log,写入到本地的 relay log 中;
            (3) SQL 线程从 relay log中获取 GTID,然后对比本地 binlog 是否有记录(所以 MySQL 从节点必须要开启 binary log);
            (4) 如果有记录,说明该 GTID 的事务已经执行,从节点会忽略;
            (5) 如果没有记录,从节点就会从 relay log 中执行该 GTID 的事务,并记录到 binlog;
            (6) 在解析过程中会判断是否有主键,如果没有就用二级索引,如果有就用全部扫描。

        综合评价:

            GTID Replication 可以认为是升级版的 Replication。

 

    5) MySQL InnoDB Cluster

        MySQL InnoDB Cluster 为 MySQL 提供了完整的高可用性解决方案。

        文档:https://dev.mysql.com/doc/refman/5.7/en/mysql-innodb-cluster-introduction.html
              
        MySQL Shell 包含 Admin API,使您可以轻松配置和管理一组至少三个 MySQL 服务器实例,以充当 InnoDB 集群。 每个 MySQL 服务器实例都运行 MySQL Group Replication,它提供了在 InnoDB 集群内复制数据的机制,具有内置故障转移功能。Admin API 无需在 InnoDB 集群中直接使用组复制。
        
        MySQL Shell 可以根据您部署的集群自动配置自身,将客户端应用程序透明地连接到服务器实例。如果服务器实例意外故障,群集将自动重新配置。在默认的单主模式下,InnoDB 集群具有单个读写服务器实例 - 主要实例。多个辅助服务器实例是主要副本的副本。如果主服务器出现故障,则辅助服务器将自动升级为主服务器。
        
        MySQL 路由器检测到此情况并将客户端应用程序转发到新主服务器。高级用户还可以将群集配置为多主结构。

        综合评价:

            InnoDB Cluster 支持自动 Failover、强一致性、读写分离、读库高可用、读请求负载均衡,横向扩展的特性,是比较完备的一套方案。但是部署起来复杂,想要解决 Router 单点问题好需要新增组件,如没有其他更好的方案暂考虑该方案。

 

 

3. 第三方优化的解决方案

    1) MMM(Master Replication Manager for MySQL)
      
        MMM(Master Replication Manager for MySQL)是在 MySQL Replication 的基础上,对其进行优化。
        
        MMM 是双主多从结构,它是 Google 的开源项目,使用 Perl 语言来对 MySQL Replication 做扩展,提供一套支持双主故障切换和双主日常管理的脚本程序,主要用来监控 MySQL 主主复制并做失败转移。

        注:这里的双主节点,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热。

        优点:

            (1) 自动的主主 Failover 切换,一般 3s 以内切换备机。
            (2) 多个从节点读的负载均衡。

        缺点:

            (1) 无法完全保证数据的一致性。如主1挂了,MMM monitor已经切换到主2上来了,而若此时双主复制中,主2数据落后于主1(即还未完全复制完毕),那么此时的主2已经成为主节点,对外提供写服务,从而导致数据不一。
            (2) 由于是使用虚拟 IP 浮动技术,类似 Keepalived,故 RIP(真实IP)要和 VIP(虚拟IP)在同一网段。如果是在不同网段也可以,需要用到虚拟路由技术。但是绝对要在同一个 IDC 机房,不可跨 IDC 机房组建集群。

    2) MHA(Master High Availability)

        MHA(Master High Availability)也是在 MySQL Replication 的基础上,对其进行优化。

        MHA 是多主多从结构,它是日本 DeNA 公司的 youshimaton 开发,主要提供更多的主节点,但是缺少VIP(虚拟IP),需要配合 keepalived 等一起使用。

        要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当 master,一台充当备用 master,另外一台充当从库。

        优点:

            (1) 可以进行故障的自动检测和转移;
            (2)具备自动数据补偿能力,在主库异常崩溃时能够最大程度的保证数据的一致性。

        缺点:

            MHA 架构实现读写分离,最佳实践是在应用开发设计时提前规划读写分离事宜,在使用时设置两个连接池,即读连接池与写连接池,也可以选择折中方案即引入 SQL Proxy。但无论如何都需要改动代码;

        关于读负载均衡可以使用 F5、LVS、HAPROXY 或者 SQL Proxy 等工具,只要能实现负载均衡、故障检查及备升级为主后的读写剥离功能即可,建议使用LVS。

    3) Galera Cluster

        Galera Cluster 是由 Codership 开发的 MySQL 多主结构集群,这些主节点互为其它节点的从节点。不同于 MySQL 原生的主从异步复制,Galera 采用的是多主同步复制,并针对同步复制过程中,会大概率出现的事务冲突和死锁进行优化,就是复制不基于官方 binlog 而是 Galera 复制插件,重写了wsrep api。

        异步复制中,主库将数据更新传播给从库后立即提交事务,而不论从库是否成功读取或重放数据变化。这种情况下,在主库事务提交后的短时间内,主从库数据并不一致。

        同步复制时,主库的单个更新事务需要在所有从库上同步 更新。换句话说,当主库提交事务时,集群中所有节点的数据保持一致。

        对于读操作,从每个节点读取到的数据都是相同的。对于写操作,当数据写入某一节点后,集群会将其同步到其它节点。

        优点:

            (1) 多主多活下,可对任一节点进行读写操作,就算某个节点挂了,也不影响其它的节点的读写,都不需要做故障切换操作,也不会中断整个集群对外提供的服务。
            (2) 拓展性优秀,新增节点会自动拉取在线节点的数据(当有新节点加入时,集群会选择出一个Donor Node为新节点提供数据),最终集群所有节点数据一致,而不需要手动备份恢复。

        缺点:

            能做到数据的强一致性,毫无疑问,也是以牺牲性能为代价。

 

  4) PXC (Percona XtraDB Cluster)

    PXC 是基于 Galera 的 MySQL 高可用集群解决方案。PXC 集群主要由两部分组成:Percona Server with XtraDB 和 Write Set Replication patches(同步、多主复制插件)。

    Galera Cluster:https://galeracluster.com/
    PXC: https://www.percona.com/software/mysql-database/percona-xtradb-cluster

 

    PXC 工作原理:

      节点接收 SQL 请求后,对于 DDL 操作,在 commit 之前,由 wsrep API 调用 Galera 库进行集群内广播,所有其他节点验证成功后事务在集群所有节点进行提交,反之 rollback。PXC 保证整个集群所有数据的强一致性,满足 CAP 理论中满足:Consistency 和 Availability。

    优点:

      (1) 高可用性,节点不可用不影响集群正常运行;
      (2) 强一致性,可以将读扩展到多个节点上;
      (3) 节点的增加数据同步自动化(IST,SST);
      (4) 可实现多点读写,但写压力仍要同步到所有节点;

    缺点:

      (1) 由于 DDL 需全局验证通过,则集群性能由集群中最差性能节点决定;
      (2) 为保证一致性,Galera 总是优先保证数据一致性,在多点并发写时,锁冲突问题严重;
      (3) 新节点加入或延后较大的节点重新加入需全量拷贝数据(SST),作为 donor 的节点在同步过程中无法提供读写;
      (4) 数据冗余度为节点数;

    名词解释:

      DDL (Data Definition Language): 简单的来说 DDL 就是对数据库的 C(Create)R(Retrieve)U(Update)D(Delete)
      IST (Incremental State Transfer): 增量同步
      SST (State Snapshot Transfer): 全量同步

 

4. 中间件

    这里简单介绍几个在部署 MySQL 数据库集群时,可能会用到的几个中间件。

    1) Apache ShardingSphere

        Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。

        ShardingSphere:https://shardingsphere.apache.org/

        (1) ShardingSphere-JDBC (sharding-jdbc)

            定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

                a) 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。
                b) 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP 等。
                c) 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,Oracle,SQLServer,PostgreSQL 以及任何遵循 SQL92 标准的数据库。

        (2) ShardingSphere-Proxy

            定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据,对 DBA 更加友好。

                a) 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用。
                b) 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端。

        (3) ShardingSphere-Sidecar(TODO)

            定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的啮合层,即 Database Mesh,又可称数据库网格。

            Database Mesh 的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互进行有效地梳理。 使用 Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。

    2) Mycat

        基于阿里开源的 Cobar 产品而研发,Cobar 的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得 Mycat 一开始就拥有一个很好的起点。一个彻底开源的,面向企业应用开发的数据库集群中间件。

        Mycat: http://mycatone.top/
        GitHub: https://github.com/MyCATApache/Mycat-Server

        功能介绍:

            (1) 支持事务、ACID、可以替代 MySQL 的加强版数据库;
            (2) 一个可以视为 MySQL 集群的企业级数据库,用来替代昂贵的 Oracle 集群;
            (3) 一个融合内存缓存技术、NoSQL 技术、HDFS 大数据的新型 SQL Server;
            (4) 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品;
            (5) MYCAT 监控
                a) 支持对 Mycat、MySQL 性能监控;
                b) 支持对Mycat的JVM内存提供监控服务;
                c) 支持对线程的监控;
                d) 支持对操作系统的 CPU、内存、磁盘、网络的监控;

        优点:

            (1) Mycat 作为主数据库中间件,是与代码弱关联的,所以代码是不用修改的,使用 Mycat 后,连接数据库是不变的,默认端口是8066。连接方式和普通数据库一样,如:jdbc:mysql://192.168.0.2:8066/;
            (2) 自带监控,提供较全面的监控服务;
            (3) 可实现数据库的读写分离,在后端的主从复制数据库集群中,通过MYCAT配置,将前台的写操作路由到主数据库中,将读操作路由到从数据库上;
            (4) Mycat 可以实现读写分离下的读操作负载均衡,将大量的读操作均衡到不同的从库上,主要出现在一主多从情形下;
            (5) Mycat 可实现数据库的高可用,在数据库主节点可用的情况下,配置一台可写从节点,这两个节点都配置在 Mycat 中,当主节点宕机时,Mycat 会自动将写操作路由到备用节点上,但并不支持在切换之后的继续主从同步;
            (6) 当读写分离已经不能满足持续增加的访问量时,Mycat 可实现数据库的垂直拆分,将所有的数据库表按照模块划分,不同类型的表拆分到不同的数据库服务器;
            (7) 随着业务量的增长,垂直拆分之后如果又出现了数据库性能问题,则需要进行水平切分,这就是俗称的分库分表。将数据量很大的表数据切分到不同的服务器库中,表结构是一样的,而使用 Mycat 实现水平切分,对前端应用是完全透明的,不用调整前台逻辑;


       Mycat 不是配置以后,就能完全解决分表分库和读写分离问题。Mycat 配合数据库本身的复制功能,可以解决读写分离的问题,但是针对分表分库的问题,不是完美的解决。或者说,至今为止,业界没有完美的解决方案。

       分表分库写入能完美解决,但是,不能完美解决主要是联表查询的问题,Mycat 支持两个表联表的查询,多于两个表的查询不支持。其实,很多数据库中间件关于分表分库后查询的问题,都是需要自己实现的,而且节本都不支持联表查询,Mycat已经算做地非常先进了。分表分库的后联表查询问题,需要通过合理数据库设计来避免。这是一套比较好的数据库集群方案,值得考虑。

    3) Haproxy

        Haproxy 是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备、虚拟主机、基于 TCP 和 HTTP 应用代理等功能。其配置简单,而且拥有很好的对服务器节点的健康检查功能(相当于 keepalived 健康检查),当其代理的后端服务器出现故障时,Haproxy 会自动的将该故障服务器摘除,当服务器的故障恢复后 Haproxy 还会自动将 RS 服务器。

        Haproxy: http://www.haproxy.org/
        GitHub: https://github.com/haproxy

        HAProxy 特别适用于那些负载特大的 Web 站点,这些站点通常又需要会话保持或七层处理。HAProxy 运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的 Web 服务器不被暴露到网络上。

        Haproxy 软件引入了 frontend,backend 的功能,frontend(acl 规则匹配)可以根据任意 HTTP 请求头做规则匹配,然后把请求定向到相关的 backend(server pools 等待前端把请求转过来的服务器组)。通过 frontend 和 backup,我们可以很容易的实现 haproxy 的 7 层代理功能,haproxy 是一款不可多得的优秀代理服务软件。

    4) Keepalived

        Keepalived 是以 VRRP 协议为实现基础的,VRRP 全称 Virtual Router Redundancy Protocol,即虚拟路由冗余协议。

        Keepalived: https://www.keepalived.org/

        虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个 master 和多个 backup,master 上面有一个对外提供服务的 vip(该路由器所在局域网内其他机器的默认路由为该 vip ),master 会发组播,当 backup 收不到 vrrp 包时就认为 master 宕掉了,这时就需要根据 VRRP 的优先级来选举一个 backup 当 master。这样的话就可以保证路由器的高可用了。

        keepalived 主要有三个模块,分别是 core、check 和 vrrp。core 模块为 keepalived 的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check 负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。

 

    5) LVS

        LVS (Linux Virtual Server),也就是 Linux 虚拟服务器。LVS 是一个实现负载均衡集群的开源软件项目,LVS 架构从逻辑上可分为调度层、Server 集群层和共享存储。从 Linux 2.4 内核以后,Linux 已经完全内置了 LVS 的各个功能模块。

        LVS 是四层负载均衡,也就是说建立在 OSI 模型的第四层 -- 传输层之上,即熟悉的 TCP/UDP,因为LVS 是四层负载均衡,因此它相对于其它高层负载均衡的解决办法,比如 DNS 域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。

        (1) LVS 调度算法
        
            静态调度:

                rr(Round Robin):轮询
                wrr(weight):加权
                sh(source hashing):源地址散列
                dh(Destination Hashing):目标地址散列

            动态调度:

                lc(Least-Connection): 最少连接
                wlc(Weighted Least-Connection): 加权最少连接
                sed(Shortest Expected Delay): 最短期望延迟
                nq(never queue): 永不排队
                LBLC(Locality-Based Least Connection): 基于本地的最少连接
                LBLCR(Locality-Based Least Connections withReplication): 基于本地的带复制功能的最少连接

        (2) LVS 三种工作模式
            
            a) VS/NAT (Virtual Server via NAT)

                优点:服务器可以运行任何支持 TCP/IP 的操作系统,它只需要一个 IP 地址配置在调度器上,服务器组可以用私有的 IP 地址。
                
                缺点:伸缩能力有限,当服务器结点数目升到 20 时,调度器本身有可能成为系统的新瓶颈,因为在 VS/NAT 中请求和响应报文都需要通过负载调度器。

            b) VS/TUN (Virtual Server via IP Tunneling)

                在 VS/TUN 的集群系统中,负载调度器只将请求调度到不同的后端服务器,后端服务器将应答的数据直接返回给用户。这样,负载调度器就可以处理大量的请求,它甚至可以调度百台以上的服务器(同等规模的服务器),而它不会成为系统的瓶颈。即使负载调度器只有 100Mbps 的全双工网卡,整个系统的最大吞吐量可超过 1Gbps。所以,VS/TUN 可以极大地增加负载调度器调度的服务器数量。VS/TUN 调度器可以调度上百台服务器,而它本身不会成为系统的瓶颈,可以用来构建高性能的超级服务器。
                
                VS/TUN 技术对服务器有要求,即所有的服务器必须支持 “IP Tunneling” 或者 “IP Encapsulation” 协议。目前,VS/TUN 的后端服务器主要运行Linux操作系统,我们没对其他操作系统进行测试。因为 “IP Tunneling” 正成为各个操作系统的标准协议,所以 VS/TUN应该会适用运行其他操作系统的后端服务器。

            c) VS/DR (Virtual Server via Direct Routing)

                跟 VS/TUN 方法一样,VS/DR 调度器只处理客户到服务器端的连接,响应数据可以直接从独立的网络路由返回给客户。这可以极大地提高 LVS 集群系统的伸缩性。跟 VS/TUN 相比,这种方法没有 IP 隧道的开销,但是要求负载调度器与实际服务器都有一块网卡连在同一物理网段上,服务器网络设备(或者设备别名)不作 ARP 响应,或者能将报文重定向 (Redirect) 到本地的 Socket 端口上。

                工作原理:

                    数据包 CIP -> VIP 发送给 LVS;
                    LVS 通过修改 MAC 地址把数据包直接发送给 RS;
                    RS 处理完成后,直接封数据包 VIP -> CIP,返回给客户端,不经过 LVS;

                限制条件:

                    RS 和 LVS 必须在同一机房中,很显然,ARP 欺骗条件要求 LVS 和 DS 要在同一个物理局域网内;
                    所有的请求报文经由 LVS,但响应报文不能经过 LVS;
                    不支持地址转换,也不支持端口映射(因为这是链路层/2层的处理,不涉及到 IP)

                注:                 
                    CIP (Client IP): 客户端 IP;
                    VIP (Virtual IP): LVS 实例 IP,一般是暴露在公网中的地址;向外部直接面向用户请求,作为用户请求的目标的 IP 地址;
                    DS (Director Server): 指的是前端负载均衡器节点;
                    RS (Real Server): 后端真实的工作服务器;

 

posted @ 2022-09-22 21:54  垄山小站  阅读(410)  评论(0编辑  收藏  举报