Spiga

幻灯片:Web开发中的缓存

2009-09-21 00:32 by Jeffrey Zhao, 13765 visits, 收藏, 编辑

这是我昨天在博文视点Open Party上海站上关于Web开发中缓存的简单讲座。原本博文视点的朋友们希望我讲一下ASP.NET MVC方面的话题(估计看我最近一直在搞这个),但是我觉得其他平台一直用的是MVC框架,而ASP.NET MVC作为“后来者”也没有什么出彩的地方,所以最终选择这个稍微“通用”些的话题。

缓存是系统性能的关键,可以说每一个高性能的系统都在这方面下过苦功。不过似乎在这一块的总结还不太多,大部分的“讨论”都是在讲,例如,缓存多么重要,Memcached多么重要,但几乎没有人讲过在某个常见场景下的解决方案“案例”,更加没有提出过如“缓存模式”这样的东西。如庄表伟同学所说那样:“经典的GoF的设计模式,其实只解决了(甚至只能说部分解决了)可重用性的需求。”。因此可以这么说,我们在经验的总结上还缺了很大一块。

不如,现在就留下你的经验吧——或者只是你的疑惑,甚至只是一个你思考过但没有解决的问题。可能别人看了就能想到:“哎,这当初我不也遇到过吗?当时我是如此如此,这般这般……”

Add your comment

35 条回复

  1. #1楼 Xuefly      2009-09-21 00:39
    抢沙发先
    我在学习Oxite2的缓存,还没开始学……
     回复 引用 查看   
  2. #2楼 ·风信子·      2009-09-21 00:50
    @Xuefly
    抢得真快

    在最近一个项目里面用了下velocity,感觉还可以,和memcached相比不知道会怎么样
     回复 引用 查看   
  3. #3楼 bluenan      2009-09-21 00:57
    最近几篇文章貌似可以读懂了。
     回复 引用 查看   
  4. #4楼[楼主] Jeffrey Zhao      2009-09-21 01:07
    @·风信子·
    估计要人搞一下性能评测比较好。
    velocity似乎好久没有新版了。
     回复 引用 查看   
  5. #5楼[楼主] Jeffrey Zhao      2009-09-21 01:07
    @bluenan
    本来就应该懂嘛。
     回复 引用 查看   
  6. #6楼 AsmInfo      2009-09-21 01:33
    大晚上不睡...
     回复 引用 查看   
  7. #7楼 kimi.hua      2009-09-21 06:51
    赵老师我想请教一个问题
    谈的正是数据缓存,我曾经构筑过一个K/V结构的缓存,当然利用的仅仅是.net 的hashtable,而sql语句 通过cache处理器来生成cachekey,来匹配hash-key值,这样实现会不会有什么问题,当然我不会把所有的cache都放到一个hash里面,会有n个进行性能分摊。

    顺便问一下,大家缓存的过期是怎么实现的,我现在是做表的缓存索引,一但某张表进行的更新,那么所有的该表关联的缓存,都将失效。

    另外如果是分布式的缓存,又怎样实现缓存的更新,就像我构建的缓存服务器,多个应用程序都会上来提取,而缓存服务器有可能是集群。

    我目前是通过一个ScanService,来确定数据库是否更新,然后有它通知缓存控制器,缓存控制器在获取通知之后,更新缓存,再分摊到各各缓存服务器中

    虽然目前运行的还算稳定,但毕竟数据量还不是很大,不知道到在高访问,和高并发时会出现什么情况,很想听听赵老师的意见

    不好意思打了那么多 so sorry
     回复 引用 查看   
  8. #8楼 kimi.hua      2009-09-21 07:04
    另外补充一下,就是关于hash在扩容的时候,例如我们最初在创建一个hash的时候,他会给一个容量,当我到达这个容量时,hash会自动重新扩容,好像是按照质数规则来扩得吧,具体得看看.net 的dll。这个时候会不会是性能瓶颈呢。
    说来惭愧,我不知道用什么方法来做压力测试才显得比较客观。
     回复 引用 查看   
  9. #9楼 DiggingDeeply      2009-09-21 09:25
    如果所有的请求都能一次命中,那么就能大大的降低能耗,不知道老赵PPT里拯救地球是不是这个意思?
    详细拜读了老赵的PPT,写的很好,通俗易懂(本人没搞过系统架构方面)。那么我有几个问题,就是缓存的关键之处是不是在于提高命中率?而不同的情景使用的缓存策略是不同的,那么大致的会分几种情形呢?缓存大概有几种形式,粒度一般来说怎么划分呢?
     回复 引用 查看   
  10. #10楼 xiao_p      2009-09-21 09:32
    楼上的问题PPT上基本都有答案,没好好看啊。
     回复 引用 查看   
  11. #11楼 Ivony...      2009-09-21 09:33
    要实现数据的缓存,我觉得应该做到以下几点:

    1、数据与行为的剥离。换言之就是应当将原有的类型剥离为Model和Controller,这样便于对数据进行缓存而不会因为行为的紧耦而出现问题。

    2、延迟加载或者说只加载马上用到的数据。简单的说数据应该在用到时加载,这样可以避免大量的数据突然涌入缓存而使得缓存机制失效。由于数据缓存的存在,也可以使得频繁逐条“加载”成为可能。

    3、优秀的缓存服务设计。这个就不多说了。
     回复 引用 查看   
  12. #12楼 Gnie      2009-09-21 09:43
    这个幻灯片组件不错~
     回复 引用 查看   
  13. #13楼 DiggingDeeply      2009-09-21 09:52
    @xiao_p
    PPT有些内容太简略了,太泛了。
    老赵不也说吗,没有好好的整理性的文章。
    理论+实际应用+数据,比较直接。
     回复 引用 查看   
  14. #14楼 葡萄园de杂烩      2009-09-21 09:58
    建议再增加下load balance环境中cache设计的挑战和解决办法
    如何平衡cache和服务器内存压力,也是容易出问题的地方
     回复 引用 查看   
  15. #15楼[楼主] Jeffrey Zhao      2009-09-21 10:00
    @葡萄园de杂烩
    呀,我这个不是为了提供一个问答区的,如果你知道这方面问题或者有经验,也可以分享一下,不要这么简单啊。
     回复 引用 查看   
  16. #16楼[楼主] Jeffrey Zhao      2009-09-21 10:00
    @DiggingDeeply
    ppt只是提纲啊。
     回复 引用 查看   
  17. #17楼[楼主] Jeffrey Zhao      2009-09-21 10:02
    @Ivony...
    没听懂,对于任何一个对象,缓存的永远只是数据,你想把“行为”缓存进去还做不到啊……
     回复 引用 查看   
  18. #18楼[楼主] Jeffrey Zhao      2009-09-21 10:04
    @DiggingDeeply
    一开始自然是开玩笑的,呵呵。
    不过能够命中缓存自然是非常重要的,一般命中率至少要70-80%吧。
    换言之,如果没有缓存,下面的存储上压力一下子要变成3-4倍,很容易直接垮掉。
     回复 引用 查看   
  19. #19楼[楼主] Jeffrey Zhao      2009-09-21 10:08
    @kimi.hua
    没听懂你的意思,根据cache处理器生成什么样的cachekey?你的目的是什么,你觉得可能会有什么问题?

    缓存的过期,一种是自动过期,一种是手动过期。要保持“即时”的话,一般必须用手动过期——或者通过某个机制帮你自动地手动过期。

    分布式缓存只是缓存存放的位置不一样,从表面上说是没有太多区别的。你的信息比较少,任何做法都不能直接说是不是合理的,一定要有上下文。
     回复 引用 查看   
  20. #20楼[楼主] Jeffrey Zhao      2009-09-21 10:11
    @kimi.hua
    .net中的hashtable实现的是可以的,不过缓存容器还需要同时保证线程安全,以及自动过期。
    如果是真对缓存容器的压力测试最简单了啊,写个程序拼命读写不就可以了吗?
     回复 引用 查看   
  21. #21楼 asheng      2009-09-21 11:00
    1.我这网速太慢 还看不到ppt
    2.据说ppt都是大纲 老赵能不能用博客的形式 再把这个内容仔细写一次呢?
    3.ps:我还很菜
     回复 引用 查看   
  22. #22楼 小赛布里      2009-09-21 11:03
    曾经有一个项目需求要求将所有的针对数据库的操作记录下来,当然只记录访问时间和操作的发起用户ID。
    这样可能会有很多在同一时间访问数据库的信息,而这些信息不可能同时写到同一个文件中(写保护?)。所以设计了一个队列链,来的消息都添加到队列里面,而这个队列则以固定频率一次性POP出所有的信息至日志文件中。
    不知道这算不算缓存。
     回复 引用 查看   
  23. #23楼 kimi.hua      2009-09-21 13:11
    @Jeffrey Zhao
    赵老师,我是按照这样的方式来处理线程安全和并发的
    Hashtable.Synchronized(new Hashtable()) 
    这样会有问题吗?


     回复 引用 查看   
  24. #24楼[楼主] Jeffrey Zhao      2009-09-21 13:25
    @kimi.hua
    你这个自然不会有并发问题了,所有操作都是互斥的。
     回复 引用 查看   
  25. #25楼[楼主] Jeffrey Zhao      2009-09-21 13:26
    @小赛布里
    我认为你这不是缓存(cache),而是缓冲(buffer)。
     回复 引用 查看   
  26. #26楼 kimi.hua      2009-09-21 13:53
    @Jeffrey Zhao
    这两天我把自己的缓存结构整理下,让赵老点评一下咯. 多谢指教
     回复 引用 查看   
  27. #27楼[楼主] Jeffrey Zhao      2009-09-21 14:15
    @kimi.hua
    多谢分享。
     回复 引用 查看   
  28. #28楼 jalor      2009-09-21 14:43
    为了我们的地球,请使用缓存.
    强烈支持老赵
     回复 引用 查看   
  29. #29楼 Ivony...      2009-09-21 22:28
    引用Jeffrey Zhao:
    @Ivony...
    没听懂,对于任何一个对象,缓存的永远只是数据,你想把“行为”缓存进去还做不到啊……


    在缓存时,我们只可能缓存数据而不是行为,但并非所有数据都是持久化的,有些数据就是存在于行为之中,为行为服务。当然这些数据最好都存放于堆栈上,但实际上很多时候字段也是一个很好的选择。

    话说我一时也很难找到合适的场景说明数据与行为不分离的情况,但实际上这在一些OO的初学者的设计中很容易找到。例如用户对象可以自行发起操作。

    数据与行为的耦合的结果造成的后果在于数据对象中包含中间结果。这使得数据对象随时都在变化,也使得数据对象不适合成为享元或单例,缓存便变得很麻烦。
     回复 引用 查看   
  30. #30楼 Ivony...      2009-09-21 22:32
    或许文笔好的朋友,可以写一篇详细的文章来阐述这件事情。

    总的来说,将数据缓存必然要将数据变为享元,这样可以最大限度节省缓存空间,也能更好地调度缓存。为了数据可以成为享元,则要尽可能的降低数据变化的可能,分离变化与不变的部分,行为则应早早的从数据对象中剥离。
     回复 引用 查看   
  31. #31楼[楼主] Jeffrey Zhao      2009-09-21 22:48
    @Ivony...
    根据我对你的话的理解加猜测加推断,是否比如说一个User对象就是个数据,但一个NHibernate的Session就是行为?
     回复 引用 查看   
  32. #32楼 YinWangLive      2009-09-22 09:16
    这个幻灯片播放器很好看啊!
     回复 引用 查看   
  33. #33楼 JimLiu      2009-09-22 10:50
    哈哈哈。。地球毁灭。。。老赵好幽默
     回复 引用 查看   
  34. #34楼 shawnliu      2009-09-22 23:06
    你这ppt太简练了 估计对一般用户帮助不大 后面consistent hash那个两张图片应该是小日本写的memcached文章的材料吧
     回复 引用 查看   
  35. #35楼 菜鸟毛      2009-10-09 15:16
    您就再大方点,把PPT的地址给我们发出来嘛.
     回复 引用 查看   
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1570701 iA0m8Tnjz9s=