架构篇三 高性能数据库集群
🎻

架构篇三 高性能数据库集群

Created
Jul 5, 2021 02:17 PM
Tags
架构

读写分离

读写分离的基本实现

  • 数据库服务器搭建主从集群,一主一从、一主多从都可以。
  • 数据库主机负责读写操作,从机只负责读操作。
  • 数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据。
  • 业务服务器将写操作发给数据库主机,将读操作发给数据库从机。

复制延迟问题

  • 写操作后的读操作指定发给数据库主服务器
  • 读从机失败后再读一次主机
  • 关键业务读写操作全部指向主机,非关键业务采用读写分离(常用)

分配机制

程序代码封装: 程序代码封装指在代码中抽象一个数据访问层(所以有的文章也称这种方式为“中间层封装”),实现读写操作分离和数据库服务器连接的管理。例如,基于Hibernate进行简单封 装,就可以实现读写分离
目前开源的实现方案中,淘宝的TDDL(Taobao Distributed Data Layer,外号:头都大了)是比较有名的。它是一个通用数据访问层,所有功能封装在jar包中提供给业务代码调 用。其基本原理是一个基于集中式配置的 jdbc datasource实现,具有主备、读写分离、动态数据库配置等功能
中间件封装: 中间件封装指的是独立一套系统出来,实现读写操作分离和数据库服务器连接的管理。中间件对业务服务器提供SQL兼容的协议,业务服务器无须自己进行读写分离。对于业务服务 器来说,访问中间件和访问数据库没有区别,事实上在业务服务器看来,中间件就是一个数据库服务器。
目前的开源数据库中间件方案中,MySQL官方先是提供了MySQL Proxy,但MySQL Proxy一直没有正式GA,现在MySQL官方推荐MySQL Router。MySQL Router的主要功能有读写分离、故障自动切换、负载均衡、连接池等, 奇虎360公司也开源了自己的数据库中间件Atlas,Atlas是基于MySQL Proxy实现的.

分库分表

业务分库

业务分库指的是按照业务模块将数据分散到不同的数据库服务器。例如,一个简单的电商网站,包括用户、商品、订单三个业务模块,我们可以将用户数据、商品数据、订单数据分开放到三台不同的数据库服务器上,而不是将所有数据都放在一台数据库服务器上。
引申出来的一些问题:
  1. join操作问题, 无法直接join关联
  1. 事务问题, 需要使用分布式事务等
  1. 成本问题, 需要多台服务器组建集群

分表

1.垂直分表 垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。 垂直分表引入的复杂性主要体现在表操作的数量要增加。原来只要一次查询就可以获取,现在需要两次及以上的查询。
2.水平分表 水平分表适合表行数特别大的表,有的公司要求单表行数超过5000万就必须进行分表,这个数字可以作为参考,但并不是绝对标准,关键还是要看表的访问性能。对于一些比较复杂的表,可能超过1000万就要分表了;而对于一些简单的表,即使存储数据超过1亿行,也可以不分表。但不管怎样,当看到表的数据量达到千万级别时, 就要警觉起来, 因为这很可能是架构的性能瓶颈或者隐患。
水平分表相比垂直分表,会引入更多的复杂性,主要表现在下面几个方面:
路由: 水平分表后,某条数据具体属于哪个切分后的子表,需要增加路由算法进行计算,这个算法会引入一定的复杂性.
join操作: 水平分表后,数据分散在多个表中,如果需要与其他表进行join查询,需要在业务代码或者数据库中间件中进行多次join查询,然后将结果合并.
count()操作: 水平分表后,虽然物理上数据分散到多个表中,但某些业务逻辑上还是会将这些表当作一个表来处理。例如,获取记录总数用于分页或者展示.
order by操作: 水平分表后,数据分散到多个子表中,排序操作无法在数据库中完成,只能由业务代码或者数据库中间件分别查询每个子表中的数据,然后汇总进行排序。

高性能NoSQL

关系型数据库的缺点(NoSQL数据库产生的原因)

  1. 关系数据库存储的是行记录,无法存储数据结构
  1. 关系数据库的schema扩展很不方便
  1. 关系数据库在大数据场景下I/O较高
  1. 关系数据库的全文搜索功能比较弱

常见的NoSQL数据库类型

  1. K-V存储:解决关系数据库无法存储数据结构的问题,以Redis为代表。
  1. 文档数据库:解决关系数据库强schema约束的问题,以MongoDB为代表。
  1. 列式数据库:解决关系数据库大数据场景下的I/O问题,以HBase为代表。
  1. 全文搜索引擎:解决关系数据库的全文搜索性能问题,以Elasticsearch为代表。

缓存架构

缓存相关问题

  1. 缓存穿透
    1. 缓存数据在数据库中就不存在
      1. 解决方案: 在缓存中设置默认值
    2. 数据从数据库中加载到缓存中时间很长, 导致压力集中在数据库上(也叫缓存击穿)
      1. 解决方案: 可以进行缓存预热, 提前加载到缓存中
  1. 缓存雪崩
    1. 缓存雪崩指的是当缓存失效(过期)后引起的系统性能急剧下降的情况, 大量请求同一时间查询数据库并同时进行数据缓存, 对数据库和缓存造成巨大的压力
      解决方案:
      1. 更新锁, 对缓存更新操作加锁, 只有获取到锁之后才能更新缓存, 其他的请求直接拒绝
      2. 后台更新, 由后台线程来更新缓存, 而不是由业务线程来更新缓存, 简单来说由后台来对缓存进行管理(缓存预热也可以用这种方案)
      3. 双key策略, 要缓存的key过期时间是t,key1没有过期时间。每次缓存读取不到key时就返回key1的内容,然后触发一个事件。这个事件会同时更新key和key1。