缓存恢恢,疏而不漏<br />——浅谈网站架构中缓存的应用<br />5173.com<br />朱晔<br />2010年6月<br />
内容概要<br />缓存的基本知识<br />网站架构中缓存的分类<br />影响缓存命中率的因素<br />缓存常见的模式和实现<br />缓存的更新过期和清除策略<br />包裹着缓存纱布的数据库<br />缓存存储方式的选择<br />缓...
缓存的基本知识<br />缓存的由来<br />两种介质的速度不匹配(差距较大)的问题导致?高速方在和低速方交互的时候因等待速度趋近于低速方,并且闲置得不到有效利用。<br />存在第三种介质,速度介于两者之间, 价格介于两者之间。通过引入这种...
缓存的基本知识<br />缓存(CACHE)和缓冲(BUFFER)<br />缓存:可以共享,多种数据,大小不固定,可以重复使用,已知数据,用于提高IO效率。<br />缓冲:不可以共享,单一数据,大小固定,读取后失效,命中100%,未知数据,...
网站架构中缓存的分类<br />按照存储介质来分<br />内存(网站进程内、同服务器独立进程、独立服务器、分布式服务器组)。<br />磁盘(本地文件和数据库,独立服务器、分布式服务器组)。<br />缓存可以使用磁盘而不仅仅是内存。<br ...
影响缓存命中率的因素<br />假设数据库的访问操作需要5毫秒。<br />第一个测试固定Key的范围,第二个测试固定缓存时间。<br /><ul><li>对于相同的请求数,随着缓存时间的上升(实时性下降),缓存命中率明显上升。
对于相同的缓存时间,随着请求数的上升(时间的推移),缓存命中率保持稳定。
在相同的缓存时间下(2秒),缓存Key的跨度越大命中率越低,往往Key的范围很大预示着缓存的粒度太粗,Key所容纳的条件太多。</li></li></ul><li>影响缓存命中率的因素<br /><ul><li>影响命中率的因素
业务需求决定的时效性(体现在缓存的过期时间)。
硬件基础结构决定的容量(即使未过期都可能会删除LRU)。
软件架构设计决定的缓存的粒度
Key = 帖子ID; Value = 所有跟贴数据。
Key = 帖子ID; Value = 一条帖子的数据  以及 Key = 帖子ID; Value = 跟贴ID列表。
缓存的设计(包括替换策略等)
提高缓存命中率的方法
权衡业务、基础结构和架构设计。
预热、增加过期时间、增加存储容量、调整缓存项的键值算法、对热点问题的捕捉。
对于时效性很高(或缓存空间有限),内容跨度很大(或访问很随机),并且访问量不高的应用来说缓存命中率可能长期接近于0,预热后的缓存还没来得及为后人服务就已经冷却。</li></li></ul><li>缓存常见的模式和实现<br />延迟加载的缓存...
依靠用户的请求加载数据
一开始命中率低(可以通过预热提高命中率)
随着用户访问的增多命中率逐渐提高
随着缓存的过期命中率保持稳定
“冷门”的数据可能始终从数据库获取
适合分布式缓存</li></ul>预加载的缓存<br /><ul><li>主要用于缓存计算前的原始大块数据
一般缓存的(元)数据不太需要更新
大多采用主动更新
一般信任缓存的数据
Upcoming SlideShare
Loading in …5
×

浅谈网站架构中缓存的应用

3,119 views
2,951 views

Published on

2010/7/17 博客园活动演讲

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,119
On SlideShare
0
From Embeds
0
Number of Embeds
366
Actions
Shares
0
Downloads
91
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

浅谈网站架构中缓存的应用

  1. 1. 缓存恢恢,疏而不漏<br />——浅谈网站架构中缓存的应用<br />5173.com<br />朱晔<br />2010年6月<br />
  2. 2. 内容概要<br />缓存的基本知识<br />网站架构中缓存的分类<br />影响缓存命中率的因素<br />缓存常见的模式和实现<br />缓存的更新过期和清除策略<br />包裹着缓存纱布的数据库<br />缓存存储方式的选择<br />缓存的同步问题<br />缓存的颠簸问题<br />分布式缓存系统的需求<br />Memcache的基本介绍<br />Memcache的使用误区和实践<br />Windows Server AppFabric Caching<br />
  3. 3. 缓存的基本知识<br />缓存的由来<br />两种介质的速度不匹配(差距较大)的问题导致?高速方在和低速方交互的时候因等待速度趋近于低速方,并且闲置得不到有效利用。<br />存在第三种介质,速度介于两者之间, 价格介于两者之间。通过引入这种介质,把低速方部分内容保存在这个介质中,高速方大多情况下无须和低速方直接交互来提高整体性能。<br />典型的例子:CPU缓存(高速方CPU低速方内存),内存(高速方CPU低速方磁盘)。<br />缓存的分类<br />硬件领域中缓存(某种介质),软件领域中的缓存(不限于某种介质,只是一种手段),我们之后谈的缓存都是软件缓存。<br />读取缓存(解决读取速度慢),写入缓存(解决写入速度慢),读写缓存。<br />狭义上解决介质读写速度不匹配问题,广义上包括任何利用中间媒介提高速度的方法,包括空间换时间,动态操作变为静态操作。<br />
  4. 4. 缓存的基本知识<br />缓存(CACHE)和缓冲(BUFFER)<br />缓存:可以共享,多种数据,大小不固定,可以重复使用,已知数据,用于提高IO效率。<br />缓冲:不可以共享,单一数据,大小固定,读取后失效,命中100%,未知数据,用于减少IO次数。<br />缓存的属性<br />命中率:从缓存中返回正确数据的次数/总请求次数。<br />容量:超过这个值启用一定的策略:转移到磁盘;转移到远端;清空部分。<br />存储介质:内存、磁盘。<br />成本:开发成本、部署成本、硬件成本。<br />效率:SET效率、GET效率、序列化、哈希算法、分布式算法。<br />缓存的限制<br />由于价格的因素,缓存实现依赖的存储往往有大小限制——保存什么,舍弃什么,命中率。<br />缓存往往是从无到有的——在最初阶段不能发挥作用,在不命中的时候性能颠簸。<br />
  5. 5. 网站架构中缓存的分类<br />按照存储介质来分<br />内存(网站进程内、同服务器独立进程、独立服务器、分布式服务器组)。<br />磁盘(本地文件和数据库,独立服务器、分布式服务器组)。<br />缓存可以使用磁盘而不仅仅是内存。<br />按照存储的数据来分<br />直接用于输出的整页(HTML、脚本样式、图片)。<br />片段页(可供多个客户端使用的HTML、脚本样式等)。<br />索引和聚合数据(空间换时间)。<br />耗时查询的结果数据。<br />和业务相关的大块数据(列表数据,引用数据)。<br />和业务相关的小级数据(行级数据,资源数据)。<br />和上下文(用户)相关的数据(活动数据)。<br />按照实现方式来分<br />框架或引擎内置的缓存(比如ORM缓存和SQL SERVER缓存)。<br />安装特定的组件根据规则自动实现缓存(比如反向代理和输出缓存)。<br />需要由开发以编程方式实现的缓存(比如业务数据缓存)。<br />按照作用来分<br />用于数据的读取(之后介绍的大部分内容都是基于此类缓存)<br />用于(允许丢失)数据的写入——写到缓存的队列中,再由工作线程提交处理(写入存储)<br />
  6. 6. 影响缓存命中率的因素<br />假设数据库的访问操作需要5毫秒。<br />第一个测试固定Key的范围,第二个测试固定缓存时间。<br /><ul><li>对于相同的请求数,随着缓存时间的上升(实时性下降),缓存命中率明显上升。
  7. 7. 对于相同的缓存时间,随着请求数的上升(时间的推移),缓存命中率保持稳定。
  8. 8. 在相同的缓存时间下(2秒),缓存Key的跨度越大命中率越低,往往Key的范围很大预示着缓存的粒度太粗,Key所容纳的条件太多。</li></li></ul><li>影响缓存命中率的因素<br /><ul><li>影响命中率的因素
  9. 9. 业务需求决定的时效性(体现在缓存的过期时间)。
  10. 10. 硬件基础结构决定的容量(即使未过期都可能会删除LRU)。
  11. 11. 软件架构设计决定的缓存的粒度
  12. 12. Key = 帖子ID; Value = 所有跟贴数据。
  13. 13. Key = 帖子ID; Value = 一条帖子的数据 以及 Key = 帖子ID; Value = 跟贴ID列表。
  14. 14. 缓存的设计(包括替换策略等)
  15. 15. 提高缓存命中率的方法
  16. 16. 权衡业务、基础结构和架构设计。
  17. 17. 预热、增加过期时间、增加存储容量、调整缓存项的键值算法、对热点问题的捕捉。
  18. 18. 对于时效性很高(或缓存空间有限),内容跨度很大(或访问很随机),并且访问量不高的应用来说缓存命中率可能长期接近于0,预热后的缓存还没来得及为后人服务就已经冷却。</li></li></ul><li>缓存常见的模式和实现<br />延迟加载的缓存<br /><ul><li>主要用于缓存计算后的小块数据
  19. 19. 依靠用户的请求加载数据
  20. 20. 一开始命中率低(可以通过预热提高命中率)
  21. 21. 随着用户访问的增多命中率逐渐提高
  22. 22. 随着缓存的过期命中率保持稳定
  23. 23. “冷门”的数据可能始终从数据库获取
  24. 24. 适合分布式缓存</li></ul>预加载的缓存<br /><ul><li>主要用于缓存计算前的原始大块数据
  25. 25. 一般缓存的(元)数据不太需要更新
  26. 26. 大多采用主动更新
  27. 27. 一般信任缓存的数据
  28. 28. 考虑初始化的时候多台服务器对数据库的冲击
  29. 29. 不适合分布式缓存</li></li></ul><li>缓存常见的模式和实现<br />操作缓存(异步队列)<br />优点是把瞬时的流量冲击“磨平”,可以控制一定的“带宽”对数据库操作,而不是“压垮”,以及不阻塞调用方线程。<br />缺点是不能保证返回结果的时间。<br />注意要平衡写入速度和处理速度,要确保缓存的容量足够大,能应付peak time。饭店生意兴旺没有座位的时候可以选择不接受新客人或是让客人排队等候,如果来的客人永远比走的客人多,那么只能考虑再开一个饭店了。<br />
  30. 30. 缓存的更新、过期和清除策略<br />缓存的更新策略<br />A 由获取数据请求触发的被动更新<br />B 由更新数据请求触发的主动更新(双写)<br />C 使用独立线程主动定时更新缓存<br />D 回调方式更新(过期或依赖)<br />E 永远不更新?<br />缓存的过期(失效)策略<br />F 绝对的过期时间<br />G 平滑过期(有人使用就不会过期)<br />H 依赖方式(依赖数据库、依赖文件)<br />I 永远不过期?<br />缓存的清除(替换)策略:<br />RAND 删除随机数据,不能反映局部性。<br />SIZE 删除最大的数据。<br />FIFO,First In First Out 删除最先进入缓存的数据,不能反映局部性。<br />LFU,Least Frequently Used 删除一直以来最少被使用的数据。<br />LRU,Least Recently Used 删除最近最少使用的数据。<br />常见模式<br />延迟加载方式:A+F<br />预加载方式:B/C/E+I<br />
  31. 31. 包裹着缓存纱布的数据库<br /><ul><li>静态资源被浏览器、反向代理挡掉,很少能击中Web服务器
  32. 32. 实时性不高的动态页,可以整页缓存在反向代理端
  33. 33. 实时性高,参数复杂的动态页,分为10个页面片段
  34. 34. 其中4个页面片段,呈现层直接在分布式缓存中找到
  35. 35. 剩余6个页面片段Web服务器无法直接获取。但所需的数据,其中4个可以由应用服务器结合自己的缓存和分布式缓存计算得到,1个由应用服务器基于内存的业务数据得到
  36. 36. 最终只有1个查询落到数据库端(还不一定需要访问磁盘)
  37. 37. 需要考虑的问题?
  38. 38. 如果数据有重叠,需要刷新缓存怎么办?
  39. 39. 开发人员各自实现自己的缓存,造成浪费,增加debug难度。</li></li></ul><li>缓存存储方式的选择<br />
  40. 40. 缓存存储方式的选择<br /><ul><li>背景:
  41. 41. 单台服务器2G内存,200G磁盘
  42. 42. 内网千兆带宽
  43. 43. 缓存5KB省市联动数据
  44. 44. 缓存10KB请求中产生的数据
  45. 45. 缓存100KB网站配置文件
  46. 46. 缓存10MB敏感过滤词列表
  47. 47. 缓存100MB游戏列表数据
  48. 48. 缓存500M CMS页面数据
  49. 49. 缓存1GB辞典原始数据
  50. 50. 缓存1GB行级发布单数据
  51. 51. 缓存1GB查询结果数据
  52. 52. 缓存100GB的报表聚合数据
  53. 53. 缓存1TB的搜索索引数据
  54. 54. 特殊情况下可否考虑多种存储联合使用?二级缓存</li></li></ul><li>缓存的同步问题<br />什么时候需要同步缓存?<br />多份相同的数据保存在多个点,比如负载均衡的应用服务器中的大块业务数据。<br />对数据实时性要求高,或是不允许数据出现不一致的现象,各自过期不能满足要求。<br />缓存同步的方式?<br />被动同步:让缓存依赖到一个点(文件、数据库等)多份缓存同时过期,不适合永不过期的大块数据,不适合主动更新的缓存,存在一定的延时。<br />主动同步:把最新的KeyValue传给各个节点,或是把需要的Key传给各个节点,由每一个节点从一个点(比如数据库或memcache)去更新最新的值(后者也可以通过独立的同步服务进行)。<br />缓存同步的问题?<br />消耗太多的资源:一份数据因为同步在网络上传多份,同步时的锁,在端点很多的时候创建过多的连接。<br />需要这么做的时候考虑一下,需要同步的数据是否适合缓存,如果是的话,是否能在单点缓存?<br />
  55. 55. 缓存的颠簸问题<br />什么是缓存的颠簸问题?<br />缓存失效后到缓存重建之间的时间内,由于用户都会访问数据库导致性能急剧下降。<br />应用服务启动的时候初始大量的数据,大量的应用服务器同时启动给数据库造成巨大压力。<br />缓存可以改善性能,但是缓存也可能会在瞬时给系统造成巨大的压力,并且,由于缓存的存在,我们很难预测数据库真正需要面对的压力,一旦缓存基础服务瘫痪,整个系统可能就瘫痪了。<br />有什么应对方法?<br />考虑让缓存永不失效,主动更新缓存,采用替换引用方式更新(主/次缓存),而不是先删除。<br />对于大块缓存的初始化考虑按需加载(延迟加载),或是尽量避免同时重启初始化服务。<br />压力测试考虑无缓存服务的情况。<br />还要注意尽量让外界无法干扰KEY的生成,否则可能会带来过多无效数据穿透缓存(比如直接根据querystring作为key来查询缓存不是好办法,不信任或不直接使用任何来自客户端的东西)。<br />
  56. 56. 分布式缓存系统的需求<br />为什么选择分布式架构?太多的理由!<br />单台服务器的资源(内存)不足以支撑我们的应用。<br />负载均衡的服务器缓存了大量相同的拷贝。<br />负载均衡的服务器缓存需要同步,或者多点更新。<br />负载均衡的服务器在缓存丢失的时候对数据库同时发起“攻击”。<br />我们有很多服务器CPU资源紧张而内存资源充足,得不到有效利用。<br />为什么存储方式选择内存?内存真不贵!<br />主要用于解决磁盘速度太慢。<br />使用CPU缓存不太现实,即使可以速度也和网络不匹配 。<br />为什么存储结构选择哈希表(Key-Value)?<br />快速——时间复杂度O(1)。<br />稳定——一直是O(1)。<br />简单——GET/SET/DEL。<br />天生就适合分布式——不需要考虑如何拆分,Key-Value的粒度足够小。<br />不过——我们要针对Key和Value的设计做很多工作,这又关于缓存的贡献度。<br />于是乎,我们想到了Memcache<br />
  57. 57. Memcache的基本介绍<br />分布式内存对象缓存系统;表现为分布式内存哈希表DHT;<br />C/S架构;客户端决定分布;服务端之间互不通信;多平台;见缝插针;<br />不是数据库;不提供故障转移;不提供容灾;不提供验证;<br />多客户端访问相同数据?序列化方式;压缩方式;哈希方式;<br />基本命令:get/set/del/add/replace/incr/decr/stats/flush/gets/cas<br />Key 250字符(超过截断);Value 1MB限制(超过失败);<br />只是字符串(有些不能序列化的数据不适合);和进程中缓存相比没有缓存指针的优势;<br />始终是缓存而不是数据库;过期时间(最长30天)和LRU(可以禁用);懒过期;<br />所有单条命令原子;1.2.5+ GETS和CAS(key, value, cas);<br />
  58. 58. Memcache的基本介绍<br />内存存储结构 Slab Allocator <br />malloc/free 慢、内存碎片 (也可使用USE_SYSTEM_MALLOC 编译开关启用)<br />以Slab(Page )1MB(其实会是小于1M Chunk Size的倍数)为单位申请内存<br />将Slab分割为固定尺寸的Chunk(-f 开关设置增长因子,默认1.25)<br />把相同尺寸的Chunk分成组也就是Slab Class(bucket)<br />选择最合适的Chunk保存,会造成浪费,以空间作为性能的tradeoff<br />如果全部空间都是10K的Chunk,之后进来的数据都是20K怎么办?重启动<br />
  59. 59. Memcache的基本介绍<br />单调性和平衡性<br />传统方式:取模,一旦节点有改变,映射全部改变<br />一致性哈希:解决单调性,平衡性通过引入虚拟节点来解决<br />
  60. 60. Memcache的基本介绍<br />
  61. 61. Memcache的使用误区和实践<br />使用误区<br />不能假设可靠性也就是100%获取到数据(比如当作static变量,或用于session)。<br />需要考虑网络开销或序列化反序列化开销(一个页面数十个请求,拆分存储大对象)。<br />Key-Value的存储决定了在设计阶段需要考虑如何使用缓存而不是在发布前去用。<br />使用实践<br />不要和需要内存的服务一起部署,可以和需要CPU的服务一起部署,不要开启SWAP。<br />定义具有意义的Key,命名空间_业务相关主键ID,而不是一段hash值:批量删除、批量获取、避免冲突,还可以在Key中包含版本号,老的数据”自然死亡“。<br />对于Value到底是保存序列化后的立体对象还是字符分隔的平面对象?比如: { { 标题 : 标题1, ID:1 } , { 标题: 标题2, ID:2 } } 还是 “标题_ID1_标题2_ID2”。<br />
  62. 62. Memcache的使用误区和实践<br />对于列表数据,可以采用两种数据结构两段式存取(IDs和行数据ID-Value),排序、查找基于IDs(可以根据条件定义多个IDs,比如news_from_0_to_100、news_category_1_top_20)而更新只需更新行数据。<br />如果没有维护IDs结构可以直接根据Key查找列表数据,比如news_2010_6_1_12_00,我们就可以实现分页列表但不能提供总页数功能。<br />善于利用append和prepend(留言添加应用,甚至可以采用命令叠加Ids:1,2,3,2d,4)。<br />善于使用批量获取来减少网络调用,必要情况下把相关的Key指定服务器保存。<br />改变思路,使用分布式缓存需要在设计阶段花一些时间,把缓存的时间和业务紧密连接并根据KeyValue的特性(不利于范围查询、搜索等)来舍弃一些不那么必要的业务功能。<br />对于需要枚举Key的应用最好具有单独的memcached集群。<br />可以基于memcache做一些扩展,比如分布式锁等等。<br />
  63. 63. Windows Server AppFabricCaching<br />什么是Windows Server AppFabric?<br />包含Caching和Hosting两部分。<br />增强有关Caching和Hosting的基础结构。<br />Windows Server AppFabric解决的问题?<br />分布式缓存<br />持久化的工作流<br />监控WCF/WF应用程序<br />基于IIS和POWERSHELL的管理工具<br />Windows Server AppFabric的优缺点<br />生产环境操作系统受限于 Windows Server 2008 SP2和Windows Server 2008 R2,基本都需要依赖.NET框架4.0。<br />功能非常完善,能做到都做了,并且可以和很多微软产品很好结合。<br />大多数组件和工具基于.NET/C#/WCF实现,不要对性能期望过多。<br />要GET START非常简单,要进行一些细节项配置比较难(界面提供的配置项过于简单),好在“开源”。<br />
  64. 64. Windows Server AppFabricCaching<br /><ul><li>Client
  65. 65. Cluster
  66. 66. Host
  67. 67. Admin tool
  68. 68. Config Storage</li></li></ul><li>Windows Server AppFabricCaching<br />编程模型<br />本地缓存<br />并发模型<br />高可用性<br />过期和清空<br />缓存通知<br />
  69. 69. Windows Server AppFabricCaching<br />演示项目 http://velocityshop.codeplex.com/<br />常见模式和应用<br />产品分类信息 New-Cache -CacheNameproductCategory -Eviction None –Expirable false<br />产品信息 New-Cache -CacheNameproduct -Eviction LRU –TimeToLive 5<br />会话信息 New-Cache -CacheNamesession –TimeToLive 1440 –Seondaries 1<br />基于regoin的存储:优势批量加载,劣势负载不够均衡<br />基于listid的存储:优势负载更均衡,劣势编程难度增加<br />常见使用技巧<br />善于使用tag,为缓存项关联多个Tag,可以查找都满足所有Tag的或满足任意Tag的项<br />结合IIS 7.5的自启动功能初始化大量起始数据<br />结合.NET 4.0并行库并行存取缓存<br />ASP.NET的会话和输出缓存可以使用AppFabric<br />Nhibernate和EF可以使用AppFabric作为二级缓存<br />
  70. 70. Q&A<br />谢谢<br />http://lovecherry.cnblogs.com<br />http://lovecindywang.cnblogs.com<br />yzhu@live.com<br />

×