- 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)
- }
- }
来自为知笔记 (Wiz) https://www.wiz.cn/i/c5b11ee0
来源: http://www.bubuko.com/infodetail-3340407.html