V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  soundbbg  ›  全部回复第 3 页 / 共 5 页
回复总数  87
1  2  3  4  5  
2014-04-25 10:46:53 +08:00
回复了 gaicitadie 创建的主题 程序员 当前用户信息该不该缓存?
需要缓存。这是结论。

如果你的网站用户量小的可怜,倒是不必,但加了还是比不加好。

这里要理解缓存和数据库的作用是同等重要的,也是需要强调的。

首先需要理解缓存,缓存你可以简单的理解成一个哈希表,通过key就可以取得值。而这个key-value对在内存中,内存的访问极快。如果数据库有索引,那也是相当的快,但索引需要生成文件,如果对大量的key进行索引会导致索引文件数据膨胀,甚至有可能会超过数据文件本身。查询虽然性能消耗的小,但大量的查询性能还是会消耗,相比之下,能节约数据库性能就节约,因为我们程序员是干嘛的?就是为了不必重复劳动。

既然lz对缓存作用有怀疑,觉得sql的查询性能已经很高了,那么我们可以仔细分析,有这么一种情况:

1个用户被100个用户关注。

OK,这样我们如果不使用缓存,加载一个用户的粉丝页面。

1. 首先通过数据库查询到用户,例如from user where id=xxx。
2. 然后通过数据库查到粉丝列表,例如from fans where follow_id=xxx。
3. 显示用户的页面,这里有101个用户。循环查询了from user where id=xxx 101次。

这个时候你会发现,即便是同一个用户,那么访问一次页面需要101个查询,虽然粉丝已经很少了。即便性能很快,还是需要消耗sql资源。如果一个页面每天被访问1000万次,你就自己能够得到结论。

如果使用缓存,会有下面的情况:

1. 首先通过数据库查询到用户,from user where id=xxx,放入缓存。
2. 通过数据库查询到粉丝列表,from fans where follow_id=xxx列表可以放入缓存。
3. 显示用户的页面,假设没有任何缓存的情况下,依旧循环查询了from user where id=xxx 100次。

这个时候再访问同一个页面的时候,假设访问1000万次。

1. 首先通过缓存看用户是否在缓存里,存在,命中返回。
2. 看用户的粉丝列表是否在缓存里,存在,命中返回。
3. 显示用户的页面,100个粉丝的用户都在缓存里,存在,命中返回。

无需数据库查询。

至于当用户的粉丝变动了,如何更新缓存呢,一个简单的方法就是删除缓存。假设用户的粉丝取消关注了这个用户。

1. 删除用户的粉丝列表的缓存。

那么刷新页面的时候就会下面的情况:

1. 首先通过缓存看用户是否在缓存里,存在,命中返回。
2. 看用户的粉丝列表是否在缓存里,不存在,查询数据库from fans where follow_id=xxx,并放入缓存。
3. 显示用户页面,99个粉丝都在缓存里,存在,命中返回。

即便访问依旧是1000万次,只有取消关注的那第一次返回查询了一个数据库,并且是lz说的高性能查询。那么数据库服务器依旧没有什么压力。

至于缓存性能?相当的快,在内存中,可以忽略不计(当然这里也是根据量级来判断,但即便千万用户也可以忽略不计)。

上面的情况只是一个业务里相当小的情况,有比如你当前打开的v2ex这个页面,加载了多少用户、话题和评论?你可以计算一下缓存的优势。

----

当然,继续深入的话,我们推荐缓存什么最好?(正确的缓存不会造成不一致)首先提出不好的:

1. 不要针对页面缓存,这才会造成什么不一致的情况。
2. 不要针对大块数据进行缓存,下面再说。

(其实有时候是可以针对一些业务页面进行缓存的,例如上个月到几年前的每个月的财务结算报表)

要缓存的,最好是最原始的数据。根据上面的情况,例如:

1. 一个用户的数据库数据的缓存。可以直接映射成一个用户的实例。
2. 一个用户的粉丝列表的id缓存,必须强调,这里不是粉丝列表的实例的缓存。

假设通过mc.get(user_key),那么得到的最好是用户数据库里的原数据。如果mc.get(user_fans_key),那么得到的就是用户粉丝的**id**缓存。这里详细说明一下,不要针对大块数据进行缓存的原因。

假设你缓存了大块数据,即拿到用户粉丝的列表不是缓存id,而是缓存对象,那么如果一个用户更新了自己的信息,这个时候并不会删除掉用户的关注列表缓存,对吧,因为粉丝并没有取消关注用户,那么关注列表拿到的用户数就错误了。

另外一个问题就是如果缓存id,即便有100万个粉丝,内存占用也不大,如果100万个实例呢。。。

所以,只针对粉丝的id进行缓存是很重要的,举例说明:

1. 用户有100个粉丝,并且缓存了。
2. 一个粉丝改了自己的名字,这个时候把粉丝的用户缓存失效。
3. 用户查询自己的粉丝时,发现99个用户缓存命中,1个用户缓存失效,查询并放入缓存。

因为在2里粉丝并没有取消关注用户,不会刷新粉丝缓存,如果这个时候缓存的是用户对象,那就出现了不一致。

----

我们可以再发散,为什么现在redis比memcached更热门,因为redis可以直接在内存里排序。假设我有一个需求是最新关注的粉丝在最上面。那么redis可以直接在缓存列表的最前面插入最新粉丝的id,但memcached不行,按上面的方法就是先删除,然后数据库里查询保持顺序,在插入到缓存中。

redis这样的情况可以让类似twitter、新浪微博这样的业务顺利进行,memcached就用起来别扭了。

----

再回到这个页面,我们看看v2ex当前页面可以怎么缓存。

1. 用户信息。
2. lz发的内容的原数据,文字可以放入key-value持久化数据库。
3. lz发的内容的评论id列表。
4. 每个评论的原数据缓存,内容可以放入key-value持久化数据库。
5. 如果有人添加评论,可以过期lz发的内容的评论id列表。
6. 如果有人更新评论,如果是内容,不需要更新缓存,直接更新持久化数据库。
7. 如果有人更新评论如时间之类的,或者删除评论,过期lz内容评论的id列表。

可以看到数据库查询大大的减少,v2ex这个用户量级和访问,至少毫秒内就能展示。

----

我不太同意『缓存』这是一个过度优化的设计,『缓存』这个概念无论是计算机硬件、软件还是web设计都是很重要的。不仅能提升app的使用体验(载入更快了),还减少了sql服务器的压力。

大部分互联网公司都及其依赖缓存,如果缓存服务器挂了,网站必然挂。但之前我也说了,缓存和数据库都是非常重要的,因为在内存中的数据断电就会消失,还是需要持久化的。另外要知道,内存的速度是硬盘访问的数百倍甚至千倍。

正如 @pubby 说的,网站运行了几年,那积累的缓存要是没了,查询流量瞬间就会击垮服务器。

几年前大家做开发的时候,喜欢把数据写入数据库,然后放入memcached,现在更多的开发更喜欢先放入redis,然后写入数据库持久化,当成是log和恢复时使用。当然我觉得可以根据业务来选择不同的方案,不一定redis是最好的(因为它太消耗内存)。

本来想解答lz的没想到说了这么多,只是觉得能反应架构和思维上的区别,当然我是一个垃圾,如果说的有问题还希望大家轻拍。
2014-04-24 11:40:13 +08:00
回复了 nooper 创建的主题 程序员 同样是略带吐槽贴。。对比老外面试和国人面试的奇葩点
好面试官可遇不可求。
求解REST API和JS技术分别是什么意思?
2014-04-19 21:07:52 +08:00
回复了 yxjxx 创建的主题 Linux 来晒晒你使用过的 Linux 命令的 top 10 吧!
1 2849 28.4928% git
2 1176 11.7612% ack
3 578 5.78058% vi
4 521 5.21052% svn
5 438 4.38044% cd
6 427 4.27043% rm
7 335 3.35034% ls
8 209 2.09021% j
9 194 1.94019% python
10 192 1.92019% cp
2014-04-17 15:57:34 +08:00
回复了 lazybios 创建的主题 程序员 有没有好的多平台协作工具推荐?
trello.
2014-04-10 18:08:49 +08:00
回复了 wdkwdkwdk 创建的主题 问与答 为了改善寝室,求推荐一个多人协作的项目的想法
哎,无所谓,别人的人生,没必要太多干涉,另外,其实打游戏不一定混的不好啊,再说,什么是好什么是不好呢?到北京工作出国加入Google、Facebook是好,难道在家乡娶妻生子其乐融融就不好了吗?

我到现在还打游戏呢。
其实觉得没有太大的用,但是『上下沟通』确实是一个很重要的问题。如果不写,公司就不知道底下的人在做什么,有时候会可能被穿小鞋。如果写,确实浪费了很多时间,重复工作。这个是个很难解决的东西。

其实最主要还是看公司的管理层的理念,但也不是说只要这样就不好。
2014-04-08 18:11:13 +08:00
回复了 blond 创建的主题 Python 如何提高 python 编程能力
提高自己计算机的基础水平,对于没遇到过的问题,不要绕开解决,尝试去理解原因。
2014-04-08 17:56:09 +08:00
回复了 yakczh 创建的主题 Python 处女座还真的适合写 python
假的多真的少,这种八卦总是喜闻乐见。
2014-04-08 14:51:03 +08:00
回复了 Livid 创建的主题 分享发现 Big Hero 6
还不错。
2014-04-08 14:50:36 +08:00
回复了 xatest 创建的主题 分享发现 豆瓣无法访问~
挂了很正常,我经常搞挂。
2014-04-07 21:43:59 +08:00
回复了 chenluois 创建的主题 程序员 想做一批热解石墨磁悬浮套件,不知有没有需求
算我一个,soundbbg在gmail。
2014-04-07 21:41:12 +08:00
回复了 wangyongbo 创建的主题 Python python 程序员 混的社区
其实也有python-china.org,但不太热闹。
触摸板难道还不够好用吗?难以理解,再者平时用鼠标用的也太多了吧?多适应适应。
2014-04-05 16:09:03 +08:00
回复了 lepture 创建的主题 昆明 昆明好地方,今天去大理
对昆明和云南感觉不错,但对丽江感觉非常不好,那里的伪文青太装了。
2014-04-03 16:12:07 +08:00
回复了 Kai 创建的主题 分享创造 分享一个为个人开发者制作的推送服务 http://notie.io
Push.co也可以。
2014-04-03 08:28:17 +08:00
回复了 StackGao 创建的主题 分享发现 时至今日都是我咎由自取
开发虽易,不挂却难,且写且珍惜。
2014-04-03 08:26:46 +08:00
回复了 sunxiaonian 创建的主题 分享发现 呃...这年头谁都做电子杂志,果壳网也出电子杂志了....
其实做电子杂志最热的不是这时候,是10年前。
Linux.
1  2  3  4  5  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5399 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 60ms · UTC 08:17 · PVG 16:17 · LAX 00:17 · JFK 03:17
Developed with CodeLauncher
♥ Do have faith in what you're doing.