redis缓存击穿解决方案(一)

谈到redis缓存,那么什么样的数据适合缓存呢?

分析一个数据是否适合缓存,我们要从访问频率、读写比例、数据一致性等要求去分析. 

那么什么又是缓存击穿呢(服务器宕机不在此讨论范围中,服务高可用)?

在高并发下,多线程同时查询同一个资源,如果缓存中没有这个资源,那么这些线程都会去数据库查找,对数据库造成极大压力,缓存失去存在的意义。

如何解决呢?

一般情况下,加锁访问数据库,伪代码如下

static Lock reenLock = new ReentrantLock();

//最后使用互斥锁的方式来实现.
  public List<String> getData() throws InterruptedException {
        List<String> result = new ArrayList<String>();
        // 从缓存读取数据
        result = getDataFromCache();
        if (result.isEmpty()) {
            if (reenLock.tryLock()) {
                try {
                    System.out.println("我拿到锁,从DB获取数据库后写入缓存");
                    // 从数据库查询数据
                    result = getDataFromDB();
                    // 将查询到的数据写入缓存
                    setDataToCache(result);
                } finally {
                    reenLock.unlock();// 释放锁
                }
            } else {//我没有拿到锁
                result = getDataFromCache();// 先查一下缓存
                if (result.isEmpty()) {
                    System.out.println("我没拿到锁,缓存也没数据,等一下");
                    Thread.sleep(100);// 
                    return getData();// 递归调用重试
                }
            }
        }
        return result;
        }
       或者采用, 队列的方式保证缓存的单线程(进程)写,写数据时加一个标识到队列中,下一个线程过来发现队列有值,不查询数据库,延时再次调用方法。

首先预防高并发访问数据库,防止缓存数据失效:

对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免对底层存储系统的查询压力。一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短。热点数据定时更新,过期时间分散开。预防后,高并发下缓存失效该如何处理呢?

一,首先

  对于,缓存对象key不变的,value值是变动的,

1,比如说网页首页要展示的一些大广告推广,这些推广是会一直展示的,但数目一段时间内是有限制的,不会一直更新,展示时间也会有条件限制,更新频率半个小时,具体时间或者实时性可根据业务自行决定,某一段时间,此缓存失效,但并发量高,访问数据库,加锁瞬间影响性能,比如秒杀活动,可用双缓存策略,俩服务布双份数据,也就是再加一个缓存服务器,此备用的缓存服务,定时更新若场景为秒杀,可适当多频率同步。主服务缓存失效后,访问备用的缓存服务器,然后更新主服务器缓存,修改主服务器缓存数据。主缓存服务器过期时间短,备用过期时间长点。

发布了23 篇原创文章 · 获赞 0 · 访问量 202

猜你喜欢

转载自blog.csdn.net/liuerchong/article/details/105130638