真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Golang的memcache怎么實(shí)現(xiàn)

這篇文章將為大家詳細(xì)講解有關(guān)Golang的memcache怎么實(shí)現(xiàn),小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)絡(luò)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、王益網(wǎng)站維護(hù)、網(wǎng)站推廣。

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

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
}

那么問(wèn)題來(lái)了:

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

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

因此,我們需要對(duì)讀寫(xiě)操作進(jìn)行加鎖:

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
}

幾點(diǎn)說(shuō)明:

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

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

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

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

關(guān)于“Golang的memcache怎么實(shí)現(xiàn)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。


網(wǎng)頁(yè)題目:Golang的memcache怎么實(shí)現(xiàn)
網(wǎng)站網(wǎng)址:http://weahome.cn/article/peoieo.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部