站長資訊網
        最全最豐富的資訊網站

        Golang的memcache如何簡單實現

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

        Golang的memcache如何簡單實現

        這兩天在做項目的過程中遇到了一個訪問全局變量的問題場景:編寫一個方法,獲取id對應的token值,token需要緩存起來(全局變量內存緩存),如果獲取不到或者token的時間過期,那么發送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變量是全局變量,那么會出現同時讀寫的情況,則會可能出現讀寫不一致的情況。

        2.就本例來看,獲取id=2的token,而緩存的token已經過期了,那么就會發送http請求去獲取,之后寫緩存,假設寫緩存的時間很長,而在這段時間內,又恰好有大量請求來獲取id=2的token,由于token都過期了,就會出現大量請求http服務端的問題,不僅沒有起到獲取緩存的目的,又增大了后端的壓力,同時又有多個寫緩存的操作,而golang的map應該不是原子的,那么大量寫內存也可能會造成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()對一個區域枷鎖,從而保證區域是可讀的,直到所有讀鎖都RUnlock()之后,才可以上寫鎖。

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

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

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 国产精品欧美一区二区三区| 天天视频国产精品| 精品无码三级在线观看视频| 国产成人精品午夜福利| 亚洲精品专区| 久久狠狠一本精品综合网| 无码精品一区二区三区免费视频| 久久精品国产亚洲AV麻豆网站| 欧美成人精品第一区二区| 亚洲国产精品欧美日韩一区二区| 1024国产欧美日韩精品| 精品人妻中文av一区二区三区| 亚洲av永久无码精品漫画| 亚洲AV无码成人精品区大在线| 国产精品五月天强力打造| 永久免费精品影视网站| 99re久久精品国产首页2020| 欧美日韩精品在线观看| 久久久久久亚洲精品不卡| 国产亚洲色婷婷久久99精品91| 99久久精品国产综合一区| 日韩精品一区二区三区四区 | 国产A∨免费精品视频| 国产精品爱啪在线线免费观看| 久久精品a亚洲国产v高清不卡| 亚洲精品无码专区在线播放| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 国产成人无码精品一区二区三区| 日韩av无码久久精品免费| 综合久久精品色| 亚洲AV无码国产精品色午友在线| 无码国产精品一区二区免费vr| 色偷偷88888欧美精品久久久 | 欧美成人精品网站播放| 老司机精品影院91| 亚洲精品高清一二区久久| 在线精品无码字幕无码AV| 中文字幕精品久久| 久久精品无码午夜福利理论片| 精品亚洲成AV人在线观看| CAOPORM国产精品视频免费|