21年11月第4题
常见的反规划化设计方法
(1)增加冗余列:#card
- 增加冗余列是指在多个表中具有相同的列,它常用来在查询时避免连接操作。
(2)增加派生列:#card
- 增加派生列指增加的列可以通过表中其他数据计算生成。它的作用是在查询时减少计算量,从而加快查询速度。
(3)重新组表:#card
- 重新组表指如果许多用户需要查看两个表连接出来的结果数据,则把这两个表重新组成一个表来减少连接而提高性能。
(4)分割表:#card
- 有时对表做分割可以提高性能。
反规范化解决数据不一致问题的方法
定期同步更新:#card
- 通过定时任务批量更新冗余字段,适合实时性要求不高的场景。
触发器同步:#card
- 在数据库中设置触发器,当源表更新时自动同步冗余字段,实时性高。
应用程序级同步:#card
- 在业务逻辑中,更新源表数据的同时也更新冗余数据,通常借助事务保持一致性。
该医药销售系统,药品数据更新频繁,采用触发器法和应用程序校验较合适。#card
- 因为它能在数据更新瞬间自动维护一致性,无需应用程序过多干预,也避免了定时任务的延迟性,可实时保证数据一致性 ,不影响系统对药品信息的实时展示和业务操作。
其中 ZSet(有序集合) 最适合实现热销药品排名 #card
因为它可以通过
score存储销量,并且支持自动排序、区间查询,非常契合排行榜场景。例如:
ZINCRBY sales 1 drugID可以为某药品销量加 1,然后通过ZREVRANGE获取销量前 N 的药品。
解决 Redis 和 MySQL 数据实时同步问题的方案 缓存与数据库的数据一致性
基于 Binlog 异步同步 。#card
用 Canal 等工具监听 MySQL 的 Binlog 日志,解析数据变更事件并推送到 Redis。
对应用透明,能捕获多种操作,可靠性高,但有延迟,部署复杂。
适用于高频写且要求最终一致场景。
应用层双写。#card
业务代码中同步写 MySQL 和 Redis,靠事务保证原子性。强一致、低延迟,但双写增加耗时,事务处理复杂。
适用于低频写、强一致场景 。
消息队列解耦。 #card
写 MySQL 后发消息到队列,消费者异步更新 Redis。
可解耦、削峰填谷,但有秒级延迟和消息堆积风险。
适用于高并发写、允许短暂不一致场景。
延迟双删。#card
更新 MySQL 前后各删一次 Redis 缓存。
简单有效,能减少不一致窗口,但极端并发下仍可能有脏数据。适用于读多写少、对一致性要求不苛刻场景。
结合数据库触发器。#card
- 在 MySQL 设触发器,监听数据变更并调外部程序更新 Redis。会增加数据库负载,维护困难。适用于遗留系统改造。