Distributed System-分布式系统 Sharding 数据切分

Distributed System 分布式系统 Sharding 数据切分

定义

数据切分(Data Partioning)是将大的数据库切分为多个小数据库
数据达到一定量后,水平扩容往往比垂直扩容更便宜

切分方法

水平切分(Horizontal Partitioning) / 范围切分(Range Based Sharding)

  • 根据数据范围进行切分,例如 ZIPCode 小于 1000 的一个表,大于 1000 的另外一个表

问题

  • 如果切分的范围选择不小心,就会出现分布不均衡

垂直切分(Vertical Partitioning)

  • 根据数据的特征进行切分,例如用户的头像信息在一个数据库,用户的好友列表在另一个数据库,图片在第三个数据库

问题

  • 如果应用数据增长,可能需要将一个特征的数据库重新切分,例如一台数据库服务器不可能处理 10B 的图片数据

地址簿切分(Directory Based Partitioning)

  • 一种松耦合(Loosely Coupled)的方式是创建一个查找服务(LookUp Service),要找到数据切分的时候,可以通过查找服务,找到对应的服务器
  • 这种方法可以在添加新的服务器时,不会影响应用

切分标准(Criteria)

  1. Key 或 基于 Hash 切分
    例如有 100 台服务器,那么 Hash 函数可以是 ID % 100
    不过如果增加一台服务器,会导致数据重分布(可以用一致性哈希解决)
  2. 列表切分(List Partitioning)
    每个分区被分配一个 Key 列表,新纪录通过判断哪个分区包含了它的 Key 来插入
    例如,北欧区包含了北欧的所有国家(Key列表),对应国家的用户记录会插入北欧区
  3. 轮询切分(Round-Robin Partitioning)
    所有分区形成一个环,然后顺时针取下一个,用于插入新纪录
  4. 组合切分(Composite Partitioning)
    组合多种切分方式

常见问题

大部分问题都是因为多个表或者同表多行不在一台设备上

Joins 操作和反范式化(Denormalization)

多表 Join 对于数据分布在不同服务器上会很慢

反范式化(Denormalization)

把数据在不同的地方多放几份,以加快数据检索速度

  • 常见做法
    • 存一些派生数据:把需要频繁重复计算的结果存起来,例如在一对多关系中,把“多”的数量作为“一”的属性存储起来
    • 预先连接(pre-joined)生成汇总表:把需要频繁join的表提前join好
    • 采用硬编码值:把依赖表中的常量值(或者不经常变化的值)直接硬编码到当前表中,从而避免join操作
    • 把详情信息纳入主表中:对于数据量不大的详情表,可以把全部/部分详情信息塞到主表中,以避免join操作
  • 代价
    • 会出现数据一致性问题

引用完整性(Referential Integrity)

大多数 RDBMS 在多台数据库服务器上不支持跨数据库的外键(Foreign Keys)约束

  • 这个只能由应用自己来保证,需要跑一些定期的 SQL 来清理一些已经被删除的空引用

重均衡(Rebalancing)

  • 很多原因导致数据分布不均衡,需要重新均衡, 例如一个 ZipCode 下面的很多地点,另一个却很少
  • 如果直接做拆分均衡,那么必然会停机(可以使用基于地址簿切分(Directory Based Partitioning)来解决)