基于ShardingSphere的数据分片

1. 为什么要分片

sharding是为了提升系统响应能力。对于数据库来说,为什么sharding会改善性能?

数据库管理数据提供增删改查功能,耗时的部分主要就是CPU计算和IO访问。单表记录规模过大:

  • 会增加表索引的大小,进而影响索引的IO读取和内存交换。
  • 会增加表数据的文件大小,进而影响最终数据的读取与扫描。
  • 记录数过多,在表扫描时需要处理更多未命中的数据。
  • 业务上,会提升单表操作并发压力。如果有触发表级锁的操作,会加重影响性能。

服务器单机硬件性能有上限,分表的基础上可以将表再分到不同的物理设备上。

2. 分表设计

分表的设计主要从业务需求上出发,主要是根据数据的查询特点来选择,从表操作SQL中必须的条件字段中选取。

例如:对于用户表,更新与加载主要是按用户操作,所以用户表的分表可以直接按用户id进行hash随机,用户及其关子表,都要和用户表保持一致的分表逻辑,因为用户子表的查询必然也会带着用户id。

分表基础上经常还会带着分库,分库分表后表连接查询就可能不支持了,所以这种情况下,要根据主要的使用场景来进行分表设计。

例如:用户好友关系表,存储用户与其好友的uid映射关系,主要的使用场景是加载好友列表(高频),分表设计时要以所有人用户id来进行分表。这里有一个问题,映射表里只有好友的uid,分库分表情况下又不能直接和用户表进行表连接,那么在加载好友列表时只能遍历按uid去获取好友的名称了。一种改进的方式是,在好友关系表中冗余存储需要随好友列表一起频繁加载的信息(比如姓名),附加同步机制来保证数据及时性。

3. sharding算法

将一个大表的数据拆分到多个表,数据的均匀性是非常重要的,这样才能平摊负载。

在数据均匀分布的前提下,只需要按分表个数直接取模就可以了。

1
2
SELECT (gcid %9) as p_gcid, count(1) as c1
FROM crm.customer_crm_search group by p_gcid;
1
2
3
4
5
6
7
8
SELECT (gcid %9) as p_gcid, count(1) as c1
FROM crm.customer_crm_search group by p_gcid;

SELECT (gcid %9) &7 as p_gcid, count(1) as c2
FROM crm.customer_crm_search group by p_gcid;

SELECT (gcid %127) &7 as p_gcid, count(1) as c3
FROM crm.customer_crm_search group by p_gcid;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# p_gcid, c1
0, 1262531
1, 1259903
2, 1259860
3, 1261827
4, 1261015
5, 1260104
6, 1261028
7, 1262103
8, 1262400

# p_gcid, c2
0, 2524931
1, 1259903
2, 1259860
3, 1261827
4, 1261015
5, 1260104
6, 1261028
7, 1262103

# p_gcid, c3
0, 1430624
1, 1431112
2, 1430266
3, 1430061
4, 1429165
5, 1429653
6, 1430281
7, 1339609

6. 参考

  1. Java Bean Copy框架性能对比
  2. 为什么阿里要求避免使用 Apache BeanUtils 进行属性复制?
  3. Performance of Java Mapping Frameworks
  4. MicroServices – DTO to Entity & Entity to DTO mapping – Libraries Comparison
  5. MapStruct Installation
  6. JMapper Philosophy