站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Golang的memcache如何簡單實現(xiàn)

        下面由golang教程欄目給大家介紹Golang簡單的memcache實現(xiàn)方法,希望對需要的朋友有所幫助!

        Golang的memcache如何簡單實現(xiàn)

        這兩天在做項目的過程中遇到了一個訪問全局變量的問題場景:編寫一個方法,獲取id對應(yīng)的token值,token需要緩存起來(全局變量內(nèi)存緩存),如果獲取不到或者token的時間過期,那么發(fā)送http請求到其他端去取,然后緩存起來,然后再返回,那么代碼如下:

        code.go:

        package person  import ( 	"time" )  var gAccId2Token map[int]interface{} = make(map[int]interface{})  func GetTokenByAccountId(accountId uint, acl string) (map[string]interface{}, error) { 	//get token from cache 	if token, ok := gAccId2Token[accountId]; ok { 		if token != nil { 			now := time.Now().Unix() 			if int(now) < int(token.(map[string]interface{})["expireDate"].(float64)) { 				return token.(map[string]interface{}), nil 			} 		} 	}  	token, err := getTokenByHttpUrl(apiUrl) 	if err != nil { 		return map[string]interface{}{}, err 	}  	gAccId2Token[accountId] = token  	return token.(map[string]interface{}), nil }

        那么問題來了:

        1.由于gAccId2Token變量是全局變量,那么會出現(xiàn)同時讀寫的情況,則會可能出現(xiàn)讀寫不一致的情況。

        2.就本例來看,獲取id=2的token,而緩存的token已經(jīng)過期了,那么就會發(fā)送http請求去獲取,之后寫緩存,假設(shè)寫緩存的時間很長,而在這段時間內(nèi),又恰好有大量請求來獲取id=2的token,由于token都過期了,就會出現(xiàn)大量請求http服務(wù)端的問題,不僅沒有起到獲取緩存的目的,又增大了后端的壓力,同時又有多個寫緩存的操作,而golang的map應(yīng)該不是原子的,那么大量寫內(nèi)存也可能會造成crash的問題。

        因此,我們需要對讀寫操作進行加鎖:

        memcache.go:

        package person  import ( 	"sync" 	"time" )  type memoryCache struct { 	lock  *sync.RWMutex 	items map[interface{}]interface{} }  func (mc *memoryCache) set(key interface{}, value interface{}) error { 	mc.lock.Lock() 	defer mc.lock.Unlock() 	mc.items[key] = value 	return nil }  func (mc *memoryCache) get(key interface{}) interface{} { 	mc.lock.RLock() 	defer mc.lock.RUnlock()  	if val, ok := mc.items[key]; ok { 		return val 	} 	return nil }  var gAccId2Token *memoryCache = &memoryCache{ 		lock:  new(sync.RWMutex), 		items: make(map[interface{}]interface{}), 	}  func GetTokenByAccountId(accountId uint, acl string) (map[string]interface{}, error) { 	//get token from cache 	token := gAccId2Token.get(accountId) 	if token != nil { 		now := time.Now().Unix() 		if int(now) < int(token.(map[string]interface{})["expireDate"].(float64)) { 			return token.(map[string]interface{}), nil 		} 	}  	token, err := getTokenByHttpUrl(apiUrl) 	if err != nil { 		return map[string]interface{}{}, err 	}  	gAccId2Token.set(accountId, token)  	return token.(map[string]interface{}), nil }

        幾點說明:

        1.為寫操作上了全局鎖,一旦Lock()之后,其他lock便不能上鎖,直到釋放鎖Unlock()之后才行,也就是說保證寫操作的原子性。

        2.而為讀操作上了讀鎖,那么可以有多個線程Rlock()對一個區(qū)域枷鎖,從而保證區(qū)域是可讀的,直到所有讀鎖都RUnlock()之后,才可以上寫鎖。

        3.將map的key和value的類型都定義成為interface{}類型,interface{}可以接收任何類型,就像是Java中的Object。

        4.interface{}類型轉(zhuǎn)換的方法,value.(type),即將value轉(zhuǎn)換成為type類型,例如:value.(int),value.(map[string]interface{})等等。

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 四虎精品亚洲一区二区三区| 国产精品区一区二区三在线播放| 亚洲精品无码av人在线观看| mm1313亚洲国产精品无码试看| 久久久久国产精品熟女影院| 欧美XXXX黑人又粗又长精品| 久久777国产线看观看精品| 亚洲精品国产字幕久久不卡| 国产午夜精品一区二区三区小说| 精品国产一区二区三区免费| 人妻精品久久无码专区精东影业| 久久夜色撩人精品国产小说| 办公室久久精品| 久久久久四虎国产精品| 99精品国产一区二区三区2021| 无码精品久久久天天影视| 日本国产精品久久| 精品久人妻去按摩店被黑人按中出| 久久久精品午夜免费不卡| 98视频精品全部国产| 国产探花在线精品一区二区| 老汉精品免费AV在线播放| 亚洲精品国产精品乱码不卞| 蜜桃麻豆www久久国产精品| 国产乱子伦精品无码专区| 99热这里只有精品国产66 | 国产成人精品a视频一区| 精品国产爽爽AV| 一本久久a久久精品综合夜夜 | 午夜影视日本亚洲欧洲精品一区| 国产精品美女久久久久| 久久婷婷国产综合精品| 久久精品中文闷骚内射| 无码日韩人妻精品久久蜜桃| 最新精品亚洲成a人在线观看| 亚洲国产精品无码久久九九| 欧美在线精品一区二区三区 | 国产精品国产AV片国产| 99久久国产综合精品网成人影院| 91精品国产麻豆国产自产在线| 一级成人精品h|