讨论一下 cache 的用法

2015-03-31 01:48:08 +08:00
 Lamian

举个实际的例子。为了减少对数据库的读操作,我们决定对部分数据加一层 cache。比如判断某 object是否为空,相应数量等等。

我的实现方式是每次数据库commit之后更新cache以防止脏数据,而且不用担心expiration的问题。如果不能hit cache, 我们就去查数据库,同时更新 cache。

我同事对此表示不同意,他的意见是 cache 本来就是性能和数据正确性之间的妥协。所以他觉得我的实现方式其实就是代替数据库,他更倾向设置一个很短的 expiration 时间,并且不去实现 after commit 的 hook,他觉得这样才是正确的使用 cache 的方法。

请问大家对 cache 的用法有什么看法?

2762 次点击
所在节点    数据库
36 条回复
kn007
2015-03-31 11:24:58 +08:00
mark。
看场景吧。
feilaoda
2015-03-31 12:14:53 +08:00
cache设置一个很短的expiration是一个很诡异的用法,只有在特殊的场景才使用

通过设置很短的expiration来达到cache数据的一致性,这个也是天才才想到的方法
sujin190
2015-03-31 12:26:08 +08:00
如果commit后写cache会增加很多复杂性和不可控性吧,如果有很多系统都使用这些数据,这样似乎很难控制啊,好吧,我一直以为cache只是用来减少数据库操作次数的和时间的
clino
2015-03-31 12:40:01 +08:00
我倾向于楼主的做法,因为这样访问到的数据比较准确

不过主要看对数据的准确程度是不是有要求,如果没有的话,倒是可以用第二种
vivisidea
2015-03-31 13:40:59 +08:00
个人更倾向于 DB commit 后 更新/清空 cache 对应的 key 的做法

设置一个很短的过期时间,多短的时间算是“很短”呢?
长了数据不一致问题会比较明显,短了 cache hit rate 降低,cache 就没啥意义了
laoyur
2015-03-31 13:58:04 +08:00
个人赞同楼主的做法,只是cache expiration time需要根据实际情况确定,或者做成可配置的之类。

另外对“DB commit 后 清空 cache”的做法表示不能理解。read from DB 需要add cache,那凭什么write to DB后居然是delete cache?write操作的优先级居然还抵不上一个read操作?
oobleck
2015-03-31 15:21:22 +08:00
两种方式都有道理

你同事的做法是一般是用户的 cache,由于通讯成本比较高,所以愿意在正确性上做一定妥协,比如浏览器的 cache

但是作为服务的提供方,数据正确应该需要保证的,并且也是可以实现的。除非数据正确性不太重要或者服务进程和数据库之间通信成本实在太高,否则没必要代替用户去做这个妥协。

楼主的 cache 实现也不常见,cache 是为读服务的,所以一般常见的做法是写之前清 cache,读 cache miss 后,从数据库读出来再写 cache
julyclyde
2015-03-31 15:31:23 +08:00
你这个其实和mysql query cache类似了
不过现在不提倡用query cache,因为清理次数太多实际上根本cache不了什么
wanjun
2015-03-31 16:09:12 +08:00
更新不频繁的数据,cache 时间长点,不考虑更新,实在要更新,手动flush

更新频繁,访问量小就不要缓存啦。

更新频繁,访问量大,直接用 redis 这样的内存数据库吧
justfly
2015-03-31 16:24:02 +08:00
说说个人的做法

读 不命中设置cache;改 清除cache

关于过期:设置cache的占用内存,达到上限缓存中理论最旧数据可以被挤出去,这样最终会导致只有热数据在cache中,个人认为这是内存和性能综合考虑的最优解。
alexapollo
2015-03-31 20:46:11 +08:00
读:不命中则读db,并设置cache
写:先写入cache,然后异步更新db

over,不明白有什么可以争论的点
ryd994
2015-03-31 23:09:17 +08:00
@alexapollo 完全不能over。writeback只是各种缓存策略之一罢了。不考虑应用场景就让别人上writeback,这是耍流氓。而且你这个策略也完全没考虑多线程。naive
alexapollo
2015-03-31 23:12:40 +08:00
@ryd994 一般都这么搞呀。如果不用这个那干嘛不上个redis或memcache就好了,这个策略多线程顶多加个锁不就结了。。。
ryd994
2015-03-31 23:20:48 +08:00
@alexapollo 用锁还是cow,加锁让谁加,这些都是问题。writethrough对这个问题就好解决得多。writeback还有异常时丢数据的事情。一般只是你身边一般而言吧。银行业务和微博,这就是两个极端,要性能还是要一致。微博偶然掉点数据根本不算事。
saberlion
2015-03-31 23:24:47 +08:00
状态的数据类似于redis实现session的用你同事的策略,页面渲染什么的不频繁更新用你的策略。
alexapollo
2015-04-01 00:12:04 +08:00
@ryd994 金融的是不能这么搞,但一般的互联网场景都可以。金融应该算少数啦。。

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

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

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

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

© 2021 V2EX