

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