如果要给 Mysql 设计缓存

2021-08-15 00:25:07 +08:00
 bushenx

场景

假设需要给 Mysql 设计一套缓存机制缓存中间件采用 Redis,让查询操作先经过缓存,在缓存没有的情况下再去查表。

问题

Redis 缓存中应该如何存储 Mysql 的数据呢?

问题描述

如果采用 Redis 的 hash 结构存储 Mysql 的一条数据,将 Mysql 的 DbName-TableName 作为 Redis Hash 的 Key,那么 field 应该使用什么呢? field 使用表的 主键 ,查询语句中带有主键的查询可以查找到这条缓存,如果查询语句中 没有主键 那应该如何处理?或者这种思路是不对的什么成熟的方案可以借鉴吗?

1619 次点击
所在节点    问与答
15 条回复
yitingbai
2021-08-15 00:36:41 +08:00
Mysql 自身就有缓存, 另外常用的 ORM 框架也带有缓存策略配合 redis 啥的, 自己实现还是很难的, 需要面面俱到, 比如你缓存了一个 sql, 记录变动你要更新缓存. 如果想学习可以去研究 orm 库的源码, 如果只是想用在项目中, 就别重复造轮子了
sutra
2021-08-15 00:39:47 +08:00
有现成的,比如 spring-data-redis 里的 RedisCache.
sutra
2021-08-15 00:42:31 +08:00
RedisCache 的默认实现方法是 cacheName::key 作为 key,序列化(可以自定义序列化和反序列化对,比如改为使用 json 格式序列化)后的数据作为 value 。不过需要注意的是,大多实现,都存在双写一致性问题。
sutra
2021-08-15 00:56:05 +08:00
顺便做个广告吧,刚写完的一个使用 Redis sorted set 来存储的 spring cache 实现,可以避免双写一致性问题。https://oxerr.org/spring-cache-redis-scored/zh/index.html
sutra
2021-08-15 01:07:12 +08:00
另外,从业务角度来讲,一般缓存的数据,不是直接的数据库查询的结果,而是经过一些计算后的更偏向于业务的结果。
sutra
2021-08-15 01:09:43 +08:00
关于双写一致性问题,我收藏了几篇文章:

Cache-Aside pattern
https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside

分布式之数据库和缓存双写一致性方案解析
https://www.cnblogs.com/rjzheng/p/9041659.html

Consistency between Redis Cache and SQL Database
https://yunpengn.github.io/blog/2019/05/04/consistent-redis-sql/
815979670
2021-08-15 02:35:52 +08:00
看具体场景把,我们这里有一个缓存思路就是
1 把查询的 sql 转换成 md5 然后 当成 key value 是 mysql 的查询结果,
2 如果有 key 就直接返回 value,如果没有就去数据库查询数据 然后缓存进 redis
3 最后给缓存的数据设置一个过期时间 我们当时给的是 5 分钟
levelworm
2021-08-15 02:52:14 +08:00
直接把常用的查询缓存在 redis 内部,保存比如三十天的量,如何?我觉得还是看什么用的最多吧,比如说查询 dau 用的最多,就直接把两个月的 dau 扔进去,每天更新一次就行了。
vindurriel
2021-08-15 10:38:34 +08:00
我觉得中间件不适合做这个 大部分读写场景不需要 少部分需要的差异又很多 key 格式 空值行为 过期时间都是变量 省不了多少事
bushenx
2021-08-15 11:03:47 +08:00
@sutra 学习了
bushenx
2021-08-15 11:07:30 +08:00
@yitingbai 我现在学习的是 Go 语言,Go 还是可以造很多轮子的,哈哈。
bushenx
2021-08-15 11:43:41 +08:00
@815979670 sql 哈希这想法属实不错
@levelworm 老铁你这法子有啥现成工具吗?
WIN2333
2021-08-15 11:49:32 +08:00
mysql 有自己的缓存,orm 也有,大部分情况下内存缓存就够了,具体问题具体分析,你这个太广了不适合都这么干,最后瓶颈会落在网络交互,以及 redis 的性能尤其是 redis 还是单线程处理的,缓存是应该是多级设计的
levelworm
2021-08-15 21:12:15 +08:00
@bushenx 没。。。我也就是一说,多半自己写了
cyrivlclth
2021-08-16 10:29:33 +08:00
@yitingbai mysql8.0 还有缓存吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/795829

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX