一般来说,网站随着访问量以及数据库的增大,访问速度将会越来越慢,如何优化这个响应速度,增大用户支持容量是网站从小到中,到大的必经之路。

你也可能听说过对于大型web站点一般严重依赖于cache来弹性放大其基础设施的能力。虽然已知大型网站都使用了cache,但是很少有比较严谨的探讨性文章来说说他们是如何来做这个cache的。其中的原因可能有几个,一方面很多cache的策略都是特定于特定网站的,很难泛化成理论。另一方面可能过于复杂,并无放之四海而皆准的策略存在,特别是cache的过时更新问题到现在为止应该还没有一个非常好的解决方案。

本文介绍几种应用广泛的缓存策略,如果使用得当,应该可以保证永远不会有过期数据访问的问题存在。其中第一个策略叫做:write-through策略,第二种叫做:generational caching.

writethrough是最简单有效的策略。当你向db写的时候,你就顺便向cache更新相应key的数据。这样的好处是,任何随后的请求总是会击中cache,而不用再打到db上返回数据。只有一种情况会打到db: cache内存已经占满,而你访问的key的value已经被清场。该策略也有一些需要注意的地方:

一般人们都会使用object id作为cache的key,但是不同的表,其id可能相同,因此在构造cache key时需要注意这一点,严格定义并且遵循一个统一的key定义规范就很重要了,比如User/17

另外,任何put/delete操作时,首先得确认该操作是否成功执行了,只有确认成功执行了,你才能去更新cache,

否额,可能就会出现db并未更新,但是cache却被更改的情况,从而db和cache就不再一致!

虽然这个策略对单个的object做cache非常有效,但是大部分应用会从db中拉取多个对象,比如(返回所有属于张三的书籍).对于操作包含多个对象的数据,我们来谈谈另一种策略"generational caching"

设想你在设计一个blog app,可能需要一个简单的posts表格包含每一个Post的信息,比如title, createdat等。一般博客类型网站需要有两种页面,一个是单博客页面,一个是博客聚类页面。比如posts/3和posts/两个页面。问题就来了,我们如何有效地对posts/这个页面的数据做好cache呢?

对单博客页面的caching前面介绍的策略非常适合:write through即可,每一个post都将映射为一个cache key(一般都是基于object type和object id,比如Post/3),而每次对一个post的更新都将write-through回cache中,保持数据的一致性。

更困难的问题是:我们如何处理博客聚类列表页面,比如home page或者category page的数据缓存?为了保证db和cache的一致性,非常重要的一点是:任何时候一个Post被update,那么所有包含该Post引用的keys都必须expired掉。而这是并不容易的事情,因为一个post可能在多个cache key中被引用,比如: latest ten posts, posts in php category, posts favorited by user 15等。虽然理论上你可以通过写代码来找到包含已更新post的所有cache key,并且手工去expire掉他,但是必须指出这个过程是非常费事费力也非常容易错误的!我们推荐另外一种思路,这个思路就是genrational caching.

这种generational caching对每种类型的object去维护一个"generation" value。每次一个object被更新,则该generation value就会被增加。依然使用post作为例子,任何时候有人更新了一个post object,我们就增加the post generation object as well. 然后,任何时候我们从cache中读或者写一组boject时,我们就包含这个generation key.

通过包含这个generation value在cache key中,任何时候一个Post被更新,那么接下来的访问就不会击中cache,因此强制回源db获取数据。这种策略的一个结果是:任何时候一个post object被更新或者删除,所有包含多个posts的keys都会隐含expired掉。之所以说是隐含,因为我们永远不会主动去删除这些objects,仅仅通过增加这个generation value,我们就能保证所有old keys永远不会被访问,下面的事情就留给cache系统本身的垃圾回收机制去处理。

在多个实际application中应用该策略后,对于cache的性能提高有以下几点认识:总的来说该策略可以大大提高应用的性能减少数据库的负载。可以节约大量的表格扫描等高密度计算能力要求。同时由于减少了对数据库的请求,其他必须访问数据库的请求也能大大加快性能。

为了保持cache的一致,这个策略相对有些保守,也就是说有可能部分不该过期的cache entry也被强制过期了。比如,如果你更新了一个特定类目下的一个Post,本策略会将所有类目的key都过期。而这看起来会有些低效率和过优化嫌疑。而我也发现大多数应用是read-heavy(重读请写)的因此这种过优化的缓存策略本身不会带来大的问题。相反,如果不适用这种略显“过优化”的简易策略,那么我们的代码实现完全是和应用,model绑定在一起的,是非常难以维护的。

我前面提过在这个策略中任何model都不会被显式地从cache中删除。这也隐含着和caching tool以及库满驱赶策略有关。一般这个cache策略会使用LRU(least recent used) eviction policy来配合使用。一个LRU策略会对那些老的keys优先从内存中移除。

web应用服务端cache策略初探的更多相关文章

  1. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  2. 如何提高Web服务端并发效率的异步编程技术

    作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...

  3. 【转载】Web移动端Fixed布局的解决方案

    特别声明:本文转载于EFE的<Web移动端Fixed布局的解决方案>.如需转载,烦请注明原文出处:http://efe.baidu.com/blog/mobile-fixed-layout ...

  4. winform客户端利用webClient实现与Web服务端的数据传输

    由于项目需要,最近研究了下WebClient的数据传输.关于WebClient介绍网上有很多详细介绍,大概就是利用WebClient可以实现对Internet资源的访问.无外乎客户端发送请求,服务端处 ...

  5. Openstack的web管理端相关

    openstack的web管理端技术方面要关注的问题. 同步?异步 先说浏览器的同步和异步,我们知道的浏览器可以使用ajax实现异步请求,就是浏览器在请求数据的时候,我们管理员还能对浏览器就行其他操作 ...

  6. android中图片的三级缓存cache策略(内存/文件/网络)

    实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且 ...

  7. 从web移动端布局到react native布局

    在web移动端通常会有这样的需求,实现上中下三栏布局(上下导航栏位置固定,中间部分内容超出可滚动),如下图所示: 实现方法如下: HTML结构: <div class='container'&g ...

  8. 教你如何实现微信小程序与.net core应用服务端的无状态身份验证

    随着.net core2的发布,越来越多人使用.net core2开发各种应用服务端,下面我就结合自己最近开发的一款小程序,给大家分享下,怎么使用小程序登录后,小程序与服务端交互的权限控制. .net ...

  9. web移动端常见问题解决方案 (转)

    总结:本文总结了web移动端的常见问题并附上解决方案,包括:Meta标签.获取滚动条的值.禁止选择文本.屏蔽阴影.css之border-box.css3多文本换行.Retina屏幕高清图片.html5 ...

随机推荐

  1. Android 开发工具类 17_setAlarm

    Alarm 是在应用程序生命周期之外设置的,所以它们十分适合于调度定时更新或者数据查询,从而避免了在后台持续运行 Service.但触发 Alarm 时,就会广播指定的 Pending Intent. ...

  2. CentOS命令行界面与图形界面切换(图文详解)

    不多说,直接上干货! Ctrl + Alt +F1,到图形界面 Ctrl + Alt +F2,到命令行界面 欢迎大家,加入我的微信公众号:大数据躺过的坑        人工智能躺过的坑       同 ...

  3. 原来你一直写错了?!实力分享一波 CSS 使用的书写规范顺序与偏门又实用的样式...

    我们在埋头写代码的时候,还要学会收集整理一些常用的代码小技巧,以便在工作时候,可以及时调取,提高工作效率. 今天,我把之前收集整理的一些CSS代码小技巧分享出来,供你参考学习,希望对你有帮助. 一.C ...

  4. IE10以下优雅降级(作为范例)

    扒下来一段 优雅降级的代码. <!--[if lt IE 10]> <style> .ie-tip{margin-top: 100px;font-size: 16px;text ...

  5. NoSQL之Redis入门笔记

    Redis 1.Redis介绍 1.1 NoSQL:一类新出现的数据库(not only sql),它的特点 不支持sql语法 存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据 ...

  6. Nodejs学习笔记(四)—与MySQL交互(felixge/node-mysql)

    简介和安装 Node.js与MySQL交互操作有很多库,具体可以在 https://www.npmjs.org/search?q=mysql  查看. 我选择了felixge/node-mysql,用 ...

  7. Date类学习总结(Calendar Date 字符串 相互转换 格式化)

    Date类学习总结 1.计算某一月份的最大天数 Calendar time=Calendar.getInstance();time.clear();time.set(Calendar.YEAR,yea ...

  8. MBIST:用于嵌入式存储器的可测试设计技术

    MBist技术可以自动实现存储器单元或阵列的RTL级内建自测试电路,MBIST的EDA工具支持多种测试算法的自动实现,可针对一个或多个内嵌存储器自动创建BIST逻辑,并完成BIST逻辑与存储器的连接, ...

  9. XML 实体

    实体可以简单的理解为引用数据项的方法,可以是普通的文本也可以是二进制数据. 实体可以分为通用实体和参数实体.通用实体用于XML当中,用于引用文本或者二进制数据,而参数实体只能在DTD中使用.通用实体与 ...

  10. C学习笔记(1)-结构体、预处理与多文件结构程序设计

    一.结构体的定义与使用 #include <stdio.h> //定义结构体(类似模板) typedef struct { char name[50]; int age; char add ...