1
jhdxr 2018-02-19 22:05:28 +08:00
知乎:先问是不是再问为什么
这么设计然后造成 DB 被打爆的架构师早就被拖出去剁了好么。。。 |
3
chenxytw 2018-02-20 11:40:23 +08:00
这得分离出一个单独的 cache 服务来处理这个逻辑吧 0 0
有些业务系统对于这种是分出两层来,一层专门做业务逻辑,一层专门做数据服务; 业务逻辑层从数据层取数据,不管数据层是从哪里取的; 而数据层来维护如贴中所说的缓存逻辑。 |
4
gouchaoer OP @chenxytw 搜到这篇文章讲了这个问题: https://huoding.com/2015/09/14/463
|
5
gouchaoer OP 实际上 apcu 也有原子的设置一个 expire 的缓存的 apcu_add,用这个就可以实现只有一个请求去更新缓存的策略,而这一切完全可以封装到原来的缓存中不用改一行逻辑代码
|
6
MeteorCat 2018-02-21 10:20:18 +08:00 via Android
这个问题区分看,如果是数据后台这种少数人管理的但是查询量大,过期所引起的 DB 层查询不足以让其崩溃;而大量请求接口级别,也需要区分,如登录接口这种单一用户请求,保存必然是 account:uid:1 这种单独某个用户的缓存信息,除非是这个用户不断恶意请求,否则该用户对于 DB 层面也不过是 where account='user'(一般有索引),基于这种情况对于 DB 层问题都不是太大,因为这是针对唯一性数据的处理;但是多人共享的数据就需要谨慎对待,同理在于抢票和限购这几种情况
|
7
mengzhuo 2018-02-21 11:29:00 +08:00 via iPhone
楼主可以参考 redis 的实现,或者直接用 redis
|
8
dangyuluo 2018-02-21 12:27:38 +08:00
如果你非得这么想的话,那么换个思路,每次请求都查询一下缓存的 TTL,10s 之内算作一个限。第一个在倒数 10s 内访问这个 cache 的,将另外一个 flag 标记为 1,然后开始从数据库里读并更新缓存,这个操作甚至可以是 block 的。其余的访问先检查下 flag,如果为 1 的话说明有别的程序正在更新缓存,我还是返回这个生命不到 10s 的缓存。
很蹩脚,不错没办法 |
9
sagaxu 2018-02-21 13:42:49 +08:00 via Android
“系统流量很大而且每个请求都用到了这个 cache ”
这种超热数据,一般量是不会太大的,我们会把它预先读入进程内 cache,用共享内存,然后定时从 db 读取刷新这些 cache,根本不走 redis,也不存在过期失效。 |
10
gouchaoer OP @sagaxu 用一个命令行程序去刷新可以啊,可是逻辑写在一起比较好吧,而且增加运维复杂度。。
|
11
inkedawn 2018-02-21 16:42:55 +08:00
重建过程加锁
or 缓存单独更新 |
12
lolizeppelin 2018-02-22 01:01:52 +08:00 via Android
可以抄 mysql query cache 实现
|
13
msg7086 2018-02-22 01:26:22 +08:00
流量很大还用过期 hit DB 设计?架构师怕不是施乐纸。
难道不是应该有一个第三方服务来监视生命周期然后主动发起数据刷新的吗? 至于你说 PHP 框架的,PHP 程序本来就是设计成非持久运行的,做不到完美更新。 你要是旁路跑一个程序专门监视生命周期,那什么都好说。 就这么裸着撸 PHP 框架里的 cache 层的应用,本来就流量小到不可能惊群。 |
14
sagaxu 2018-02-22 02:21:34 +08:00 via Android
@gouchaoer php 里是不大好弄,其它语言里随便开个定时器就搞定了。php 碰到这种需求,只能用 swoole 这类方案了,2.0 开始大量借鉴了 Go 的特性。单进程的优越性在这种场景下特别明显。
|
15
puritania 2018-02-27 10:19:26 +08:00
换种思路? cache 永不过期,数据变更时你主动更新 cache。
|