大型网站系统与Java中间件实践 第5章 数据访问层

数据库水平/垂直拆分的困难

给数据库减压

  • 优化应用
  • 缓存、搜索引擎
  • 数据库拆分

垂直拆分带来的问题

  • 单机的ACID保证被打破了,单机事务被破坏,要么放弃单机事务,要么引入分布式事务
  • 一些Join 操作会变得比较困难
  • 靠外键进行约束的场景会受到影响

    水平拆分带来的问题

  • ACID被打破
  • Join操作被影响
  • 外键约束场景受影响
  • 单独的自增序列受影响
  • 对单个逻辑意义上的表的查询要跨库了

分布式事务相关理论

一些理论

  • 分布式事务规范 XA
  • CAP/BASE 理论
  • 比两阶段提交更轻量一些的Paxos协议

集群内数据一致性的算法实例

  • Quorum
  • Vector Clock

多机的Sequence问题

ID的唯一性和连续性

使用独立的服务生成ID序列

性能问题
稳定性问题,ID生成器作为一个无状态的集群存在,其可用性要靠整个集群保证
存储问题

两种方式:独立ID生成器方式;生成器嵌入应用方式;

多机的数据查询

跨库join

集中解决思路:

  • 多次查询 数据冗余
  • 转为单表查询
  • 借助外部系统(搜索引擎)

外键约束

这个问题比较难解决,需要靠应用层的判断、容错等方式了。

数据访问层的设计与实现

数据访问层实现方式

  • 专有API
  • JDBC方式
  • ORM接口

数据划分

  1. 固定哈希算法
    根据某个字段(例如用户ID)取模,将数据分到不同的数据库和表中。 除了根据ID取模,还经常会根据时间维度来划分数据,这一般用于数据产生后相关数据不修改的情况,否则就要涉及数据移动的问题了。固定哈希的规则设置和实现都很简单,不过如果扩容的话就比较复杂,会涉及到数据迁移。
  2. 一致性哈希算法
    一致性哈希所带来的最大的变化就是把节点对应的哈希值变为了一个范围,而不再是离散的。在一致性哈希中,我们会把整个哈希值的范围定义得非常大,然后把这个范围分配给现有的节点。如果有节点加入,那么这个新节点会从原有的某个节点上分管一部分范围的哈希值;如果有节点退出,那么这个节点原来管理的哈希值会给它下一个节点来管理。

    1. 虚拟节点对一致性哈希的改进
      该方案是为了解决一致性哈希增减节点后导致系统节点负载不均而设计的。简单说就是把一个物理节点变成成很多个虚拟节点。这样就可以解决负载不均匀的问题。

    2. 映射表与规则自定义计算方式
      映射表是根据分库分表字段的值的查表法来确定数据源的方法,一般用于对热点数据的特殊处理,或者在一些场景下对不完全符合规律的规则进行补充,常见的情况是以前面的方式为基础,配合映射表来用。
      规则自定义方式是最灵活的方式,它已经不算是以配置的方式来做规则了,而是通过比较复杂的函数计算来解决数据访问的规则问题。可以说是扩展能力最强的一种方式。我们可以通过自定义函数来计算最终的分库。

读写分离

  1. 数据结构相同,多从库对应一主库,并且从库只复制主库中的一部分数据,也就是在从库上进行了分库。这种场景如何实现?
  2. 主备库分库方式不同的数据复制,也就是非对称复制,比如主库的分库条件是按照买家的id进行分库的,而备库的分库条件是根据卖家的id进行分库的。这两种分库方式是为了方便买家和卖家查询自己的订单是不用跨库查询。这种场景下,就需要实现非对称复制。
  3. 数据变更平台,复制到其他数据库是数据变更的一种场景,还有其他场景也会关心数据的变更,例如搜索引擎的索引构建、缓存的失效等。我们可以考虑构建一个通用的平台来管理和控制数据变更。

如何做到数据的平滑迁移

对数据库做平滑迁移的最大挑战是,在迁移过程中又会有数据的变化。可以考虑的方案是,在进行迁移数据的时候,记录增量日志,迁移结束后,再对增量的变化进行处理。在最后,可以把要被迁移的数据的写暂停,保证增量日志都处理完毕,在切换规则放开所有的写,完成迁移工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值