-
在社交系统中,点赞操作频繁,若每次点击都直接更新数据库,将导致严重的数据库压力,尤其在高并发场景下可能引发性能瓶颈甚至服务雪崩。
本方案通过 Redis 缓存点赞增量 + 阈值触发/定时同步数据库 实现点赞数据的弱一致性缓存,以此提高系统吞吐量、降低数据库压力,并兼顾数据一致性和系统可用性。
点赞操作不直接更新数据库,而是先更新 Redis 中的“点赞增量”值,并在满足以下条件之一时将其同步至数据库:
- 增量值达到指定阈值(如
50次); - 定时任务每
10 分钟检查并将现有增量统一入库。
Redis Key 类型 说明 post:{id}:like_count_deltaString 帖子 {id}点赞的增量post:{id}:like_countString 帖子 {id}点赞总数缓存lock:post:{id}String 用于并发写入加锁
- 使用 Lua 脚本将以下 3 步操作合并为原子操作:
INCRBY点赞增量;EXPIRE设置过期时间(如 12 分钟);- 判断是否超过阈值;
- 若增量达到阈值(例如 50 次),尝试加 Redis 锁(key:
lock:post:{id}); - 加锁成功后,读取增量并写入数据库;
- 最后更新总点赞数缓存并清空 delta 增量键。
原始版本中
incrementLikeCount0()存在三步操作非原子性问题,可能导致重复写库或数据错乱,故已弃用。- 优先读取缓存键
post:{id}:like_count; - 若无缓存,则读取数据库原始值 + 当前 Redis 中的点赞增量;
- 结果写入总点赞缓存,设置过期时间(如
12分钟); - 返回总点赞数。
⚠️ 注:缓存过期策略需结合同步频率综合设置,避免频繁失效导致穿透。- 每隔
10 分钟执行一次; - 扫描所有
post:*:like_count_delta的键(使用keys); - 尝试为每个 postId 获取写锁;
- 获取成功后同步 Redis 增量到数据库,并删除该增量键;
- 最后同步总点赞数缓存。
统一调用方法
redisToMysql()完成以下操作:- 使用
MyBatis-Plus UpdateWrapper实现点赞字段自增; - 删除点赞增量缓存(
DELkey); - 更新 Redis 中点赞总数缓存。
java复制编辑updateWrapper.eq("id", postId) .setSql("like_count = like_count + " + likeCountDelta);
参数名 数值 说明 LIKE_COUNT_DELTA50(个点赞数) 点赞增量阈值,达到后触发入库 LIKE_COUNT_UPDATE_INTERVAL10 分钟 定时任务入库间隔 LIKE_COUNT_DELTA_EXPIRE_TIME12 分钟 点赞增量键过期时间,避免空键长期保留
- 有效减轻数据库压力,适用于高并发场景;
- 使用 Redis 锁+Lua 脚本,解决并发一致性问题;
- 可拓展性强,支持分布式部署;
- 弱一致性:点赞数在短时间内存在延迟;
- Redis 异常/丢失会造成增量丢失(建议搭配 AOF 或 RDB 持久化);
- 使用
keys命令会阻塞 Redis,后续可替换为SCAN;
- ✅ 持久化方案增强:开启 AOF 持久化降低数据丢失风险;
- ✅ 性能优化:定时任务使用
SCAN替代keys; - ✅ 精细锁粒度:可以将
lock:post:{id}替换为 Redisson 分布式锁;
- 增量值达到指定阈值(如
-
Notifications
You must be signed in to change notification settings - Fork 0
banalord/FindFood
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
About
No description, website, or topics provided.
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published