memcached一般用于在访问一些性能相对低下的数据接口时(如数据库),为了保证这些数据接口的稳定性,加上memcached以减少访问次数,保证这些数据接口的健壮性。一般memcached的数据都是定时失效的,当数据失效时一般会再次去访问取数据接口,然后将其更新至memcached中。这时就会有一个问题,当某个数据失效时,恰好同时有大量的客户端访问该数据,这时这些客户端都会发现该数据失效,然后都会去调用数据接口去取数据更新,这自然就瞬间地使数据接口失去了memcached的保护,有可能造成系统的故障。

那么如何解决这个问题呢?

第一种:数据不失效,定时更新。即数据存放在memcached中永不失效,但是会有一个定时任务,定时的去更新这个数据。

第二种:既然该问题的症结在于在数据失效时,会有多个客户端去调用数据接口,那么只要想办法在数据失效时只有一个客户端能访问数据接口即可,要做到这点,自然的想法是加锁:如下:

  1. object value = memcached.get(key);
  2. if(null==value){
  3. synchronized{
  4. value = memcached.get(key);
  5. if(null==value){
  6. value = db.get(key);
  7. memcached.set(key,value);
  8. }
  9. }
  10. }
  11. return value;

这样做的前提是你必须保证这个函数的类是单例的,显然在服务器集群中不可能有这样的场景,那么如果在群集间加锁呢?解铃还需系铃人,既然大家共用一个memcached服务器,那么就使用memcached来实现这个锁机制。即当客户端取不到数据时,先在memcached中设置一个flag表明当前客户端在更新该数据,当其它客户端也来访问时发现失效后就等待直到更新好数据为目。

  1. object value = memcahced.get(key);
  2. if(null=value){
  3. if(memcached.add(key)){
  4. value = db.get();
  5. memcached.set(key,value);
  6. }else{
  7. while(true){
  8. Thread.sleep(50);
  9. value=memcached.get(key);
  10. if(null!=value){
  11. break;
  12. }
  13. }
  14. }
  15. }
  16. return value;

memcached中的add方法是实现该功能的关键,该方法是判断memcached中是否有某个key存在,如果存在则返回false,否则返回true,并添加该key值,如果没有该方法,显然我们只能再一次的通过get 和set去设置该值,显然这样做是线程不安全的,有可能有多个客户端同时取为空,同时去取数据并更新。

上述的方法存在的缺陷时,一旦数据失效,所有客户端要等待某个客户端更新完毕,这样势必增加服务器压力,可以通过在key失效之间的一段时间就触发更新的方式来解决这个问题。

memcached缓存失效时的高并发访问问题解决的更多相关文章

  1. 应对Memcached缓存失效,导致高并发查询DB的四种思路(l转)

    当Memcached缓存失效时,容易出现高并发的查询DB,导致DB压力骤然上升. 这篇blog主要是探讨如何在缓存将要失效时,及时地更新缓存,而不是如何在缓存失效之后,如何防止高并发的DB查询. 解决 ...

  2. 应对Memcached缓存失效,导致高并发查询DB的几种思路

    原文地址: http://blog.csdn.net/hengyunabc/article/details/20735701 当Memcached缓存失效时,容易出现高并发的查询DB,导致DB压力骤然 ...

  3. [转]高并发访问下避免对象缓存失效引发Dogpile效应

    避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...

  4. 高并发访问mysql时的问题(一):库存超减

    如果在对某行记录的更新时不采取任何防范措施,在多线程访问时,就容易出现库存为负数的错误. 以下用php.mysql,apache ab工具举例说明: mysql表结构 CREATE TABLE `yx ...

  5. Memcached理解笔记4---应对高并发攻击

    近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...

  6. ql Server 高频,高并发访问中的键查找死锁解析

    死锁对于DBA或是数据库开发人员而言并不陌生,它的引发多种多样,一般而言,数据库应用的开发者在设计时都会有一定的考量进而尽量避免死锁的产生.但有时因为一些特殊应用场景如高频查询,高并发查询下由于数据库 ...

  7. Sql Server 高频,高并发访问中的键查找死锁解析

    死锁对于DBA或是数据库开发人员而言并不陌生,它的引发多种多样,一般而言,数据库应用的开发者在设计时都会有一定的考量进而尽量避免死锁的产生.但有时因为一些特殊应用场景如高频查询,高并发查询下由于数据库 ...

  8. OpenResty + Lua访问Redis,实现高并发访问时的毫秒级响应打回

    一.lua中redis的配置依赖: 1.OpenResty的lua访问redis的插件:https://github.com/openresty/lua-resty-redis 二.下载后,导入对应的 ...

  9. Java集群--大型网站是怎样解决多用户高并发访问的

    时间过得真快,再次登录博客园来写博,才发现距离上次的写博时间已经过去了一个月了,虽然是因为自己找了实习,但这也说明自己对时间的掌控能力还是没那么的强,哈哈,看来还需不断的努力啊!(这里得特别说明一下本 ...

随机推荐

  1. MyBatis入门(三)---多个参数

    一.建立表 1.1.建立表,并插入数据 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.6.27-log : Database - mybatis *** ...

  2. 【转】Windows的多线程编程,C/C++

    在Windows的多线程编程中,创建线程的函数主要有CreateThread和_beginthread(及_beginthreadex). CreateThread 和 ExitThread    使 ...

  3. 原生JS获取各种高度宽度、浏览器窗口滚动条的位置、元素的几何尺寸名

    1)关于 pageX, clienX,offsetX,layerX pageX:鼠标在页面上的位置,从页面左上角开始,即是以页面为参考点,不随滑动条移动而变化 clientX:鼠标在页面上可视区域的位 ...

  4. JavaScript Patterns 3.1 Object Literal

    Basic concept Values can be properties: primitives or other objects methods: functions User-defined ...

  5. PS网页设计教程XXVII——设计一个大胆和充满活力的作品集

    作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,“熟读唐诗三百首,不会作诗也会吟”. 本系列的教程来源于网上的PS教程,都是国外的,全英文的.本人尝试 ...

  6. 深入PHP内核之in_array

    无意中看到一段代码 1.a.php <?php $y="12"; $x = array(); for($j=0;$j<50000;$j++){ $x[]= " ...

  7. cordova Process finished with exit code -1

    安装完cordova之后,创建一个测试项目后,运行报Process finished with exit code -1,经过查找原因,是因为gradle没有安装,在http://www.androi ...

  8. TarJan 算法求解有向连通图强连通分量

    [有向图强连通分量] 在有向图G中,如果两个 顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的 ...

  9. sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用

    SYNOPSIS #include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); in ...

  10. linux内核宏container_of

    首先来个简单版本 /* given a pointer @ptr to the field @member embedded into type (usually * struct) @type, r ...