實現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)
    }


}





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM