web应用服务端cache策略初探
一般来说,网站随着访问量以及数据库的增大,访问速度将会越来越慢,如何优化这个响应速度,增大用户支持容量是网站从小到中,到大的必经之路。
你也可能听说过对于大型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策略初探的更多相关文章
- 关于如何提高Web服务端并发效率的异步编程技术
最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...
- 如何提高Web服务端并发效率的异步编程技术
作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...
- 【转载】Web移动端Fixed布局的解决方案
特别声明:本文转载于EFE的<Web移动端Fixed布局的解决方案>.如需转载,烦请注明原文出处:http://efe.baidu.com/blog/mobile-fixed-layout ...
- winform客户端利用webClient实现与Web服务端的数据传输
由于项目需要,最近研究了下WebClient的数据传输.关于WebClient介绍网上有很多详细介绍,大概就是利用WebClient可以实现对Internet资源的访问.无外乎客户端发送请求,服务端处 ...
- Openstack的web管理端相关
openstack的web管理端技术方面要关注的问题. 同步?异步 先说浏览器的同步和异步,我们知道的浏览器可以使用ajax实现异步请求,就是浏览器在请求数据的时候,我们管理员还能对浏览器就行其他操作 ...
- android中图片的三级缓存cache策略(内存/文件/网络)
实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且 ...
- 从web移动端布局到react native布局
在web移动端通常会有这样的需求,实现上中下三栏布局(上下导航栏位置固定,中间部分内容超出可滚动),如下图所示: 实现方法如下: HTML结构: <div class='container'&g ...
- 教你如何实现微信小程序与.net core应用服务端的无状态身份验证
随着.net core2的发布,越来越多人使用.net core2开发各种应用服务端,下面我就结合自己最近开发的一款小程序,给大家分享下,怎么使用小程序登录后,小程序与服务端交互的权限控制. .net ...
- web移动端常见问题解决方案 (转)
总结:本文总结了web移动端的常见问题并附上解决方案,包括:Meta标签.获取滚动条的值.禁止选择文本.屏蔽阴影.css之border-box.css3多文本换行.Retina屏幕高清图片.html5 ...
随机推荐
- 【数组】Minimum Path Sum
题目: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right w ...
- Postman—参数化
一.单个数据参数化 场景:购物车接口,需要用到登录接口返回的token 1.登录接口,在Tests里面设置usertoken环境变量,用来保存token值. 2.获取购物车接口使用usertoken变 ...
- Linux用户权限规范 /etc/sudoers文件解释
# User privilege specification root ALL=(ALL) ALL # Members of the admin group may gain root privile ...
- LR问题集合
LR如何解决低维不可分 特征映射:通过特征变换的方式把低维空间转换到高维空间,而在低维空间不可分的数据,到高维空间中线性可分的几率会高一些.具体方法:核函数,如:高斯核,多项式核等等. 从图模型角度看 ...
- xgb 绘制
1.windows安装Graphviz2.38 安装地址:https://graphviz.gitlab.io/_pages/Download/Download_windows.html 2.在pyt ...
- koa2开发入门
一.koa2入门 1.创建koa2工程 首先,我们创建一个目录hello-koa并作为工程目录用VS Code打开.然后,我们创建app.js,输入以下代码: // 导入koa,和koa 1.x不同, ...
- 【LeetCode题解】231_2的幂(Power-of-Two)
目录 描述 解法 1:判断整数 \(x\) 的二进制表示中是否只有一位为1 实现方式 1:除以 2 Java 实现(非递归) Python 实现(非递归) Java 实现(递归) Python 实现( ...
- histoty显示时间戳
设置Linux可以查看历史命令的执行时间 大家都知道Linux平台上,可以通过history命令查看最近所执行过的命令,但history命令默认所显示的只有编号和命令的,只知道命令是最近所执行 ...
- catch异常
int ret = -1; try { ret = tBuyerCodeApplyInfoService.insertTBuyerCodeApplyInfoBySelective(buyerCode) ...
- [转]使用C#进行图像处理的几种方法
最近做监控图像由彩色变灰处理的时候发现图像处理过程中,很慢很慢代码如下: int Height = this.picInfo.Image.Height; int ...