久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

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

      Golang的memcache如何簡(jiǎn)單實(shí)現(xiàn)

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

      Golang的memcache如何簡(jiǎn)單實(shí)現(xiàn)

      這兩天在做項(xiàng)目的過程中遇到了一個(gè)訪問全局變量的問題場(chǎng)景:編寫一個(gè)方法,獲取id對(duì)應(yīng)的token值,token需要緩存起來(lái)(全局變量?jī)?nèi)存緩存),如果獲取不到或者token的時(shí)間過期,那么發(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 }

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

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

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

      因此,我們需要對(duì)讀寫操作進(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.為寫操作上了全局鎖,一旦Lock()之后,其他lock便不能上鎖,直到釋放鎖Unlock()之后才行,也就是說(shuō)保證寫操作的原子性。

      2.而為讀操作上了讀鎖,那么可以有多個(gè)線程Rlock()對(duì)一個(gè)區(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號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)