memcached作为缓存系统
基本模型
如图,FE表示front server(如web server)
Read:前端server向memcache请求数据
- 如果命中则直接返回数据
- 如果数据在memcache中miss,则前段server会自己向后端db请求数据,然后再将返回的数据set到memcache中
Write:前段server向db发送写请求,然后从memcache中delete(k),将更新的数据删除掉
问题
这边有个问题就是为什么在读数据miss的时候,不由memcache来向db请求数据并缓存。
look aside:即为上述所讲由前端server向db请求数据
look through : 由memcache来请求数据
原因有二:
- 缓存层作为一个独立的系统,不跟后端db耦合,既不需要知道db信息
- 往往缓存的数据不是从db读出来的直接数据,是经过前端server处理过的数据,这样下次读取的时候,省去了处理的时间。
在写的时候,为什么不是直接更新db和memcache,而是在memcache通过删除使数据无效。
设想这样一种情况,如图
两个client更新同一个数据,c1先更改为1,c2后更改为2,但是向memcache的set请求是c2先到达的,则以后的client读到的一直是过时的数据1。在facdbook保证的是最终一致性,即允许某时刻读到的不是最新的数据,但是最终会读到这个最新的数据,而上述情况则违反了这一一致性原则。相反使用使无效机制,这种情况则不会发生,无论使无效请求谁先到达。
缓存系统中常见的两个问题:
- stale set:即client向memcache中set一个过时的值,设想这样一种情况,c1读缓存miss然后去请求db然后发送set操作请求,这时候另外一个前端server改写了同样的数据。然后发送invalidate,这个时候如果c2读缓存也是miss,则会向db请求最新数据然后更新cache。如果memcache得到的请求顺序是这样的,即invalidate,c2的set,最后才是c1的set。这样就产生了set过时的值。
- thundering herds:意思是当有个某个热点数据,被多个前端server频繁访问,当该热点数据别修改时并使无效,这时候,会有同时多个读请求到达cache,然后都会发现数据miss,接着同时去请求后端db,这样就导致了后端db的请求数激增。
解决:lease
- 当cache中数据miss时,返回给前端server一个token,该tonken与该数据绑定,当向memcache中set数据时,提供该token,memcache会验证该tokern是否失效,如果数据被invalidate了那么该token就会验证失败,解决了1问题
- 限制返回给前端server的toker速率,假设,每间隔10s ,memcache才会给另一个server发送toker,若在10s内有多个server来访问数据,且数据miss,则只会给第一个server发送token,其他的server以某种机制通知他们等待几秒钟,这样在这等待的几秒钟,可能第一个就已经把miss的数据set到cache中去了。
可能第一个就已经把miss的数据set到cache中去了。