
1) 【一句话结论】采用垂直分库(按业务模块拆分表,如用户、作业、错题本分库)与水平分片(按用户ID哈希分表)结合的分库分表策略,通过分布式事务(如Seata)或最终一致性(结合消息队列与补偿机制)保证多端同步(如错题本)的数据一致性。
2) 【原理/概念讲解】分库分表是为了应对海量数据存储与查询性能。垂直分库是将不同业务表(如用户表、作业表、错题本表)按业务拆分到不同数据库实例(如用户表在库A,作业表在库B),减少单库压力;水平分片是将同一张表按数据量或ID范围拆分成多个分表(如作业表按用户ID哈希分片,每个分表存储部分用户数据),分散数据量。数据一致性方面,分布式系统事务需考虑网络延迟与节点故障,强一致性(如2PC)可能导致阻塞,实际中常用最终一致性,通过消息队列(如Kafka)传递更新,并设置超时重试或补偿任务(如定时检查数据一致性)。
类比:垂直分库像把不同功能的房间(用户信息、作业记录、错题本)分开存放,水平分片像把每个房间的大衣柜(作业表)拆成多个小抽屉(分表),每个抽屉放不同用户的东西,这样总容量大,取东西(查询)更快。
3) 【对比与适用场景】
| 方式 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 垂直分库 | 按业务模块拆分表(如用户表、作业表分库) | 单库表数减少,跨库查询复杂 | 业务模块多,单表数据量大的场景(如用户表关联多个表,作业表关联错题本) | 跨库事务复杂,查询需JOIN多个库 |
| 水平分片 | 按数据量或ID范围拆分表(如按用户ID哈希分表) | 单表数据量分散,查询性能提升 | 单表数据量极大(如作业表每日百万条),需要水平扩展 | 分片键选择影响数据分布,分片后查询需路由到对应分片 |
数据一致性模型对比:
| 模型 | 定义 | 特性 | 适用场景 |
|---|---|---|---|
| 强一致性 | 任何操作后,所有节点数据立即一致 | 事务提交后,所有副本立即更新 | 对数据实时性要求高的场景(如金融交易) |
| 最终一致性 | 操作后,数据可能延迟一致,最终会一致 | 通过消息队列、补偿机制保证 | 海量数据、高并发场景(如社交网络、电商订单) |
4) 【示例】假设作业表(作业数据)按用户ID哈希分片,表名为assignment_user_<hash(user_id)>,分片数量为8。用户A的ID为1001,哈希后对应分片0,其作业数据存入assignment_user_0。错题本表按用户ID范围分片,表名为wrong_problem_user_<range(user_id)>。数据一致性实现:当用户在APP端添加错题本时,通过Seata分布式事务确保作业表(分片0)和错题本表(分片1)同时更新,事务提交后,Kafka发送“错题本更新”消息,后端消费者处理消息并同步其他端数据,若消费者延迟,定时任务检查并同步数据。
伪代码(分片路由):
def get_assignment_table(user_id):
shard_id = hash(user_id) % 8
return f"assignment_user_{shard_id}"
5) 【面试口播版答案】面试官您好,针对作业帮作业批改系统存储海量作业数据的需求,我会采用垂直分库+水平分片的分库分表策略,并配合分布式事务(如Seata)或最终一致性方案保证数据一致性,具体思路如下:
首先,分库分表设计:将核心表按业务拆分(如用户表、作业表、错题本表分别部署在不同数据库实例,垂直分库),再将作业表按用户ID哈希分片(水平分片),比如作业表拆分为8个分表,每个分表存储部分用户数据,这样单表数据量控制在合理范围,提升查询性能。
其次,数据一致性保障:对于错题本多端同步,采用最终一致性+补偿机制,当用户在APP端添加错题本时,通过Seata分布式事务确保作业表和错题本表同时更新,事务提交后,消息队列(如Kafka)发送更新消息,后端消费者处理消息并同步其他端数据,若消费者延迟,定时任务检查并同步数据,保证最终一致性。
6) 【追问清单】
7) 【常见坑/雷区】