自動緩存-對緩存策略的補充方案

緩存的目的都是爲了減少跟數據庫的直接交互,提高可用性。常用的方法如,對熱點數據緩存、對部分數據預加載、對頻繁操作的數據放到緩存中操作等等。
在開發的過程中,我嘗試了一種自動處理緩存的方法,記錄下,以供參考。
在業務代碼,和ORM之間,引入一個模塊(SaSql)。將對於數據庫的操作,分爲單行操作、list操作,即讀寫單條記錄,和讀寫多條記錄。
以list爲例:
SaSql獲取list數據時,優先從緩存拿,沒有則通過ORM從數據庫拿。核心代碼示意如下:

//讀取緩存
cacheParams := &map[string]string{}
if ignoreCache == false {
	saData.Merge(cacheParams, pk)
	saData.Merge(cacheParams, ma)
	if err = saCache.ListGet(tblName, cacheParams, aryPtr); err == nil && aryPtr != nil {
		return nil
	} else {
		if onlyCache {
			return err
		}
	}
}

//讀取數據庫
if err := session.Find(aryPtr); err == nil {
	//寫入緩存
	if ignoreCache == false {
		saCache.ListSet(tblName, cacheParams, aryPtr)
	}

	return nil
} else {
	return err
}

示例中,saCache則是緩存處理,其中,將參數以k_v的形式組合成字符串,作爲Redis緩存的key。假如獲取同一張表的list,但是參數不同,則會緩存成兩條記錄。

該方案只是緩存的補充手段,對於緩存數量要有限制,因爲同一條數據,可能會出現在多條緩存記錄中(因爲不同參數都會單獨緩存),會出現較多的重複數據,浪費空間。
示例代碼中,對分頁數據,只緩存前2頁數據,就是基於次點考慮。

以下爲獲取緩存Key的示意代碼:

func listKey(tbl string, params *map[string]string) (key string) {
	if tbl == "" || params == nil {
		return ""
	}

	key = revel.AppName + "_" + tbl + "_list_"

	var keyAry []string
	for k := range *params {
		keyAry = append(keyAry, k)
	}
	sort.Strings(keyAry)

	for i, k := range keyAry {
		key += saUtils.SnakeStr(k) + "=" + (*params)[k]
		if i+1 < len(keyAry) {
			key += "_"
		}
	}
	return
}

此方案的優點是,可以應對突發或者意向之外的流量,作爲主要緩存策略的一個補充。
再者,每次取數據,都會先走緩存,而Redis是單線程(不考慮最新版本的),對於請求會自動做排隊,也會降低數據庫壓力。

附上基於此方案的壓測結果

Server Software:        
Server Hostname:        xxx
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128

Document Path:          xxx
Document Length:        23 bytes

Concurrency Level:      100
Time taken for tests:   484.310 seconds
Complete requests:      250000
Failed requests:        1
   (Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors:           0
Non-2xx responses:      249999
Total transferred:      155999376 bytes
HTML transferred:       5749977 bytes
Requests per second:    516.20 [#/sec] (mean)
Time per request:       193.724 [ms] (mean)
Time per request:       1.937 [ms] (mean, across all concurrent requests)
Transfer rate:          314.56 [Kbytes/sec] received

最後安利一個自己寫的小程序,不喜請忽略
歡迎加微信交流 yf_good134
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章