实现redis缓存,缓存穿透简单原理

String get(String key) {  
   String value = redis.get(key);  
   if (value  == null) {  
    if (redis.setnx(key_mutex, "1")) {  //设置分布式锁,同一时刻只能有一个线程能进行此操作
        // 3 min timeout to avoid mutex holder crash  
        redis.expire(key_mutex, 3 * 60)  
        value = db.get(key);  //为锁设置过期时间,防止持有锁的线程down了 锁没法释放,导致死锁
        redis.set(key, value);  //将过期的缓存重新放入redis
        redis.delete(key_mutex);  //操作完成后释放锁
    } else {  
        //其他线程休息50毫秒后重试  
        Thread.sleep(50);  //其他线程等待之后又重新去获取,这时候redis里面过期的数据已经被重新加载了
        get(key);  
    }  
  }  
}

func GetTopicDetail(c *gin.Context)  {
    tid:=c.Param("topic_id")
    topics:=Topics{}
    // DBHelper.Find(&topics,tid)
    //c.JSON(200,topics)
    conn:=RedisDefaultPool.Get()
    redisKey:="topic_"+tid
    defer conn.Close()
    ret,err:=redis.Bytes(conn.Do("get",redisKey))
    if err!=nil{ //缓存里没有
        DBHelper.Find(&topics,tid)
        retData,_:=ffjson.Marshal(topics)
        if topics.TopicID==0{ //代表从数据库没有匹配到
            conn.Do("setex",redisKey,20,retData) //设置20s过期时间
        }else{//正常数据 50秒缓存
            conn.Do("setex",redisKey,50,retData)
        }
        c.JSON(200,topics)
        log.Println("从数据库读取")
    }else{//代表有值
        log.Println("从 redis读取")
        ffjson.Unmarshal(ret,&topics)
        c.JSON(200,topics)
    }


}




猜你喜欢

转载自www.cnblogs.com/hualou/p/12071040.html