转:http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac

目前高并发项目会在数据库之上引入数据缓存:

1. 缓存雪崩,什么是雪崩效应?

缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

我的理解的雪崩效应是在分层服务调用的系统中,当一个较为基础的服务a因某种原因不可用,导致其调用服务b,c也不可用,而b的不可用又导致其调用服务e,f的不可用,不可用的服务就好像滚雪球一样越滚越大,最后导致系统出现严重故障。我们称之为雪崩效应。如图。

以此为例,当数据库主备都不可用时,将导致其调用服务的关联失效(红色组件)

2.基于redis数据过时失效的策略,在缓存过期的短时间内存在数据库短暂压力问题,如下:

为解决上述问题(主要是后者),可采用一下解决方案如下:

这里我们以两个键值对的缓存代替之前的一个,将缓存时间(key-time),和缓存数据(key-data)分离,这样

1.当缓存过期时,第一个线程发现key-time没有,则先更新key-time,

2.然后去查询数据库(或任何比较耗时的数据查询方式),并更新key-data的值,

3.当后续线程来获取数据时,虽然第一个还没有从数据库查完并更新缓存,但发现key-time存在,会获取旧的数据。

虽然按这种方式获取的数据中c类型的数据为旧数据,但可以做到:

在缓存过期时不至于在短时间内对数据库造成较高压力(解决第2个问题)。

在数据库不可用,同时缓存过期的时候,其调用服务皆不可用,造成连锁反应,而已该解决方式,则可以返回过期数据,为修复数据库赢得宝贵时间(缓解雪崩效应)

示例代码:

Redis 获取数据
public static String get(String key) {
      Jedis jedis = null;
      int redisIndex = RedisUtils.getRedisIndex(key);
      try {
         jedis = getRedis(redisIndex);
         jedis.select(1);
         // 缓存过期  && 获取锁成功
   // setnx:原子操作,如果不存在则设置值,并返回1。如果缓存存在,则返回0,设置缓存失败
         if(jedis.setnx("lock_"+key, System.currentTimeMillis()+"")==1){
            /**
             *  将锁的有效时间设为60s,在60s内如果查询数据库成功,则更新该锁的失效时间=缓存时间。
             *  如果60s内出现异常,则60s后第一个请求又会去访问数据库...
             *  返回null表示没有查询到数据库,外层代码会通过数据库获取数据
             */
            jedis.expire("lock_"+key, 60);
            return null;
         }
         // (缓存未过期) || (缓存过期,但是获取锁失败) then 返回旧的数据
         else{
            jedis.select(0);
            return jedis.get(key);
         }
      } catch (JedisException e) {
         if (jedis != null) {
            returnBrokenResource(jedis, redisIndex);
            // 避免在finally中再次关闭reids
            jedis = null;
         }
         throw e;
      } finally {
         if (jedis != null) {
            returnResource(jedis, redisIndex);
         }
      }
   }
 
Redis 缓存数据
public static boolean set(String key, String value, int seconds) {
      Jedis jedis = null;
      int redisIndex = RedisUtils.getRedisIndex(key);
      try {
         jedis = getRedis(redisIndex);
         if (seconds > 0){
            // 添加缓存,缓存有效时间=真实时间+1天
            jedis.setex(key, seconds + 60 * 60 *24 , value);
            jedis.select(1);
            // 添加缓存锁,有效时间 =真实时间
            jedis.setex("lock_" + key, seconds, System.currentTimeMillis()+"");
         }else{
            jedis.set(key, value);
            jedis.select(1);
            jedis.set("lock_" + key, System.currentTimeMillis()+"");
         }
         return true;
      } catch (JedisException e) {
         if (jedis != null) {
            returnBrokenResource(jedis, redisIndex);
            // 避免在finally中再次关闭reids
            jedis = null;
         }
         throw e;
      } finally {
         if (jedis != null) {
            returnResource(jedis, redisIndex);
         }
      }
   }

转:Redis 缓存策略的更多相关文章

  1. redis 缓存策略

    redis 缓存策略配置项:maxmemory <bytes>maxmemory-policy noeviction 触发时机:每次执行命令(processCommand)的时候会检测 w ...

  2. Redis缓存策略设计及常见问题

    Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...

  3. mysql+redis缓存策略常见的错误

    什么时候应该更新缓存 应该是从数据库读取数据后,再更新缓存,从缓存读取到数据,就不需要再重新写缓存了,一个常见的错误是,每次访问接口都更新缓存,这样的话,如果接口一直有流量,那么db中的数据,就一直没 ...

  4. Redis缓存策略

    常用策略有“求留余数法”和“一致性HASH算法” redis存储的是key,value键值对 一.求留余数法 使用HASH表数据长度对HASHCODE求余数,余数作为索引,使用该余数,直接设置或访问缓 ...

  5. 在Window系统中使用Redis缓存策略

    Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近 ...

  6. Redis的缓存策略和主键失效机制

    作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略. >>EXPIRE主键失效机制 在Redis当中,有生存期的key被称为volatile,在创建缓存时,要为给定的key设置 ...

  7. 浅谈一下缓存策略以及memcached 、redis区别

    缓存策略三要素:缓存命中率   缓存更新策略  最大缓存容量.衡量一个缓存方案的好坏标准是:缓存命中率.缓存命中率越高,缓存方法设计的越好. 三者之间的关系为:当缓存到达最大的缓存容量时,会触发缓存更 ...

  8. redis 缓存用户账单策略

    最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...

  9. 缓存策略:redis缓存之springCache

    最近通过同学,突然知道服务器的缓存有很多猫腻,这里通过网上查询其他人的资料,进行记录: 缓存策略 比较简单的缓存策略: 1.失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放 ...

随机推荐

  1. D. Fedor and coupons 二分暴力

    http://codeforces.com/contest/754/problem/D 给出n条线段,选出k条,使得他们的公共部分长度最大. 公共部分的长度,可以二分出来,为val.那么怎么判断有k条 ...

  2. Listview多种布局的使用

    ListView中有两个可以用来让ListView可以在视图中显示多种布局的方法,分别是getItemType和getViewTypeCount 其中 getItemViewType返回的是有参数po ...

  3. Android 仿 新闻阅读器 菜单弹出效果(附源码DEMO)

    这一系列博文都是:(android高仿系列)今日头条 --新闻阅读器 (一) 开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉 ...

  4. Java运行报错问题——Picked up JAVA_TOOL_OPTIONS: -agentlib:jvmhook

    http://blog.csdn.net/xifeijian/article/details/8830933 上述这个朋友博文提醒,可能是因为其他软件添加了JAVA_HOME的路径造成冲突.但他支持删 ...

  5. Android开发: 关于性能需要考虑的

    刚做Android开发时,只管完成任务,将需求完成,以能完成一款界面酷炫的app为自豪.然而,随着代码量的增加,越来越意识到,一款成功的移动端产品,光有酷炫的外衣还不够,还需要在各方面都优秀. 试想, ...

  6. ListView用法

    public class MainActivity extends Activity implements OnItemClickListener, OnScrollListener { privat ...

  7. windows多线程应用编程注意事项

    1,资源争用保护 对于文件操作.界面资源.GDI操作等一般由主线程完成的任务,要加以顺序化处理(serialization),即一个资源一次只能由一个线程访问,多个线程同时访问将导致错误. 方法一般可 ...

  8. JavaScript开发心得--如何传递某行数据给下一页

    1, 应用场景 在某个html页面显示一批数据,如20个用户的名称.年龄等,每行都要一个编辑按钮,点击编辑后,将此行数据带入某个专门的编辑页进行显示,修改后保存. 问题是 点击编辑按钮后,如何得知要编 ...

  9. Slow HTTP Denial of Service Attack 漏洞解决办法

    编辑 删除 问题名称: Slow HTTP Denial of Service Attack 问题URL http://10.238.*.*:58*** 风险等级: 高 问题类型: 服务器配置类 漏洞 ...

  10. [转]Js获取当前日期时间及其它操作

    转载自:http://www.cnblogs.com/carekee/articles/1678041.html Js获取当前日期时间及其它操作 var myDate = new Date();myD ...