转: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. 290 Word Pattern 单词模式

    给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循这种模式.这里的 遵循 指完全匹配,例如在pattern里的每个字母和字符串 str 中的每个非空单词存在双向单映射关系 ...

  2. [译]Cookies Without Chocolate Chips

    Cookies Without Chocolate Chips In the HTTP sense, a cookie is a name with an associated value. A se ...

  3. mac当你有多个版本的命令存在是怎么使用最新版本

    例如你安装了一个最新的git.然而系统中由于xcode等自带的git的存在.使得/usr/bin/git 是xcode的版本. 只需要再 ~/.bash_profile 中添加一行优先path即可 e ...

  4. Angular——单页面实例

    基本介绍 1.引入的route模块可以对路由的变化做出响应 2.创建的控制器中依然需要$http向后台请求数据 3.php中二维数据的遍历用的是foreach 4.php中$arr=array(),$ ...

  5. DOM节点例子

    elementNode.setAttribute(name,value) 1.name: 要设置的属性名. 2.value: 要设置的属性值. elementNode.getAttribute(nam ...

  6. oracle数据库跨库查询

    create public database link mylink connect to orclname identified by orclpasswd using 'ORCL'; drop p ...

  7. Java Servlet DAO实践(二)

    Java Servlet DAO实践(二) DAO连接类 package com.seller.servlets.dao; import java.sql.*; public class DataBa ...

  8. POJ_3041_Asteroids

    参考自: http://user.qzone.qq.com/289065406/blog/1299322465 解题思路: 把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1.V2,其中| V1 ...

  9. CAD得到所有组名(网页版)

    主要用到函数说明: _DMxDrawX::GetAllGroupName 得到所有组名. js代码实现如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  10. CAD与用户交互在图面上选择一个实体(com接口VB语言)

    主要用到函数说明: IMxDrawUtility::GetEntity 与用户交互到在图面上选择一个实体,详细说明如下: 参数 说明 [out] IMxDrawPoint** pPickPoint 返 ...