文档章节

Golang解决缓存miss后的刷新缓存带来的数据库读取压力

Kyli
 Kyli
发布于 2016/10/18 18:02
字数 311
阅读 66
收藏 1
Go

工作中碰到缓存失败时,数据库的惊群,本来之前用Redis的SETNX来做锁处理,后来想想,既然用golang写了服务,当然可以把锁直接做在内存里,就自己写了一小段代码。

package resourceslock

import (
	"errors"
	"sync"
)

var (
	Lock resourcesLock = resourcesLock{
		lockerMapMtx:     new(sync.Mutex),
		lockerMap:        make(map[ResourceTopic]chan void),
		topicWaitlistMtx: make(map[ResourceTopic]*sync.Mutex),
		topicWaitlist:    make(map[ResourceTopic][]chan bool),
	} // universal lock
	voidMsg void = void{}
)

type ResourceTopic string
type ProtectCondition func() bool
type ReloadFunc func() (interface{}, error)
type void struct{}
type resourcesLock struct {
	lockerMapMtx     *sync.Mutex
	topicWaitlistMtx map[ResourceTopic]*sync.Mutex
	lockerMap        map[ResourceTopic](chan void)
	topicWaitlist    map[ResourceTopic][](chan bool)
}

func (self *resourcesLock) Protect(topic ResourceTopic, cond *ProtectCondition, reload *ReloadFunc) error {
	if (*cond)() == true {
		return nil
	}

	var err error
	self.createLockChn(topic)

	select {
	case <-self.lockerMap[topic]:
		_, err = (*reload)()
		if err != nil {
			self.notifyError(topic)
		} else {
			self.notifySuccess(topic)
		}
		self.lockerMap[topic] <- voidMsg
	default:
		if !<-self.addToWaitlist(topic) {
			err = errors.New("Resource is not refreshed.")
		}
	}

	return err
}

func (self *resourcesLock) createLockChn(topic ResourceTopic) {
	self.lockerMapMtx.Lock()
	_, ok := self.lockerMap[topic]
	if !ok {
		ch := make(chan void, 1)
		ch <- voidMsg
		self.lockerMap[topic] = ch
		self.topicWaitlistMtx[topic] = new(sync.Mutex)
	}
	self.lockerMapMtx.Unlock()
}

func (self *resourcesLock) addToWaitlist(topic ResourceTopic) <-chan bool {
	ch := make(chan bool)
	self.topicWaitlistMtx[topic].Lock()
	self.topicWaitlist[topic] = append(self.topicWaitlist[topic], ch)
	self.topicWaitlistMtx[topic].Unlock()

	return ch
}

func (self *resourcesLock) notifyError(topic ResourceTopic) {
	self.notify(topic, false)
}

func (self *resourcesLock) notifySuccess(topic ResourceTopic) {
	self.notify(topic, true)
}

func (self *resourcesLock) notify(topic ResourceTopic, suc bool) {
	self.topicWaitlistMtx[topic].Lock()
	for i, c := range self.topicWaitlist[topic] {
		if suc {
			c <- true
		} else {
			c <- false
		}
		self.topicWaitlist[topic][i] = nil
	}
	self.topicWaitlist[topic] = self.topicWaitlist[topic][:0]
	self.topicWaitlistMtx[topic].Unlock()
}

 

© 著作权归作者所有

Kyli
粉丝 4
博文 25
码字总数 4526
作品 0
高级程序员
私信 提问
Android学习系列(27)--App缓存管理

无论大型或小型应用,灵活的缓存可以说不仅大大减轻了服务器的压力,而且因为更快速的用户体验而方便了用户。 Android的apk可以说是作为小型应用,其中99%的应用并不是需要实时更新的,而且诟...

andyhe91
2015/04/23
78
0
分布式系统先写DB还是先缓存?

本文我们将深入到实际场景中,聚焦「缓存」,来看一下「进程内缓存」、「进程外缓存」运用时的一些最佳实践。 由于篇幅原因,这次先聊三个问题。首先就是我们应该“先写DB还是缓存?”。我想...

DBAplus社群
05/13
0
0
缓存架构设计细节二三事

本文主要讨论这么几个问题: (1)“缓存与数据库”需求缘起 (2)“淘汰缓存”还是“更新缓存” (3)缓存和数据库的操作时序 (4)缓存和数据库架构简析 一、需求缘起 场景介绍 缓存是一种...

问题达人
2016/03/31
57
2
缓存架构设计细节二三事 (一)

本文主要讨论这么几个问题: (1)“缓存与数据库”需求缘起 (2)“淘汰缓存”还是“更新缓存” (3)缓存和数据库的操作时序 (4)缓存和数据库架构简析 一、需求缘起 场景介绍 缓存是一种...

snowing1990
2016/03/14
74
0
缓存架构设计细节二三事

本文主要讨论这么几个问题: (1)“缓存与数据库”需求缘起 (2)“淘汰缓存”还是“更新缓存” (3)缓存和数据库的操作时序 (4)缓存和数据库架构简析 一、需求缘起 场景介绍 缓存是一种...

Java_Coder
2016/03/28
174
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
32分钟前
5
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
35分钟前
4
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
4
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
8
0
前端技术之:webpack热模块替换(HMR)

第一步:安装HMR中间件: npm install --save-dev webpack-hot-middleware 第二步:webpack配置中引入webpack对象 const webpack = require('webpack’); 第三步:增加devServer配置项: ho......

popgis
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部