日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrame緩存管理-內(nèi)存緩存

緩存組件默認提供了一個高速的內(nèi)存緩存,操作效率非常高效,?CPU?性能損耗在?ns?納秒級別。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序定制開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了陽信免費建站歡迎大家使用!

使用示例

基本使用

package main

import (
	"fmt"
	"github.com/GOgf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gctx"
)

func main() {
	// 創(chuàng)建一個緩存對象,
	// 當(dāng)然也可以便捷地直接使用gcache包方法
	var (
		ctx   = gctx.New()
		cache = gcache.New()
	)

	// 設(shè)置緩存,不過期
	err := cache.Set(ctx, "k1", "v1", 0)
	if err != nil {
		panic(err)
	}

	// 獲取緩存值
	value, err := cache.Get(ctx, "k1")
	if err != nil {
		panic(err)
	}
	fmt.Println(value)

	// 獲取緩存大小
	size, err := cache.Size(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(size)

	// 緩存中是否存在指定鍵名
	b, err := cache.Contains(ctx, "k1")
	if err != nil {
		panic(err)
	}
	fmt.Println(b)

	// 刪除并返回被刪除的鍵值
	removedValue, err := cache.Remove(ctx, "k1")
	if err != nil {
		panic(err)
	}
	fmt.Println(removedValue)

	// 關(guān)閉緩存對象,讓GC回收資源
	if err = cache.Close(ctx); err != nil {
		panic(err)
	}
}

執(zhí)行后,輸出結(jié)果為:

v1
1
true
v1

過期控制

package main

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gctx"
	"time"
)

func main() {
	var (
		ctx = gctx.New()
	)
	// 當(dāng)鍵名不存在時寫入,設(shè)置過期時間1000毫秒
	_, err := gcache.SetIfNotExist(ctx, "k1", "v1", time.Second)
	if err != nil {
		panic(err)
	}

	// 打印當(dāng)前的鍵名列表
	keys, err := gcache.Keys(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(keys)

	// 打印當(dāng)前的鍵值列表
	values, err := gcache.Values(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(values)

	// 獲取指定鍵值,如果不存在時寫入,并返回鍵值
	value, err := gcache.GetOrSet(ctx, "k2", "v2", 0)
	if err != nil {
		panic(err)
	}
	fmt.Println(value)

	// 打印當(dāng)前的鍵值對
	data1, err := gcache.Data(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(data1)

	// 等待1秒,以便k1:v1自動過期
	time.Sleep(time.Second)

	// 再次打印當(dāng)前的鍵值對,發(fā)現(xiàn)k1:v1已經(jīng)過期,只剩下k2:v2
	data2, err := gcache.Data(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(data2)
}

執(zhí)行后,輸出結(jié)果為:

[k1]
[v1]
v2
map[k1:v1 k2:v2]
map[k2:v2]

GetOrSetFunc*

?GetOrSetFunc?獲取一個緩存值,當(dāng)緩存不存在時執(zhí)行指定的?f func() (interface{}, error)?,緩存該?f?方法的結(jié)果值,并返回該結(jié)果。

需要注意的是,?GetOrSetFunc?的緩存方法參數(shù)?f?是在緩存的鎖機制外執(zhí)行,因此在?f?內(nèi)部也可以嵌套調(diào)用?GetOrSetFunc?。但如果?f?的執(zhí)行比較耗時,高并發(fā)的時候容易出現(xiàn)?f?被多次執(zhí)行的情況(緩存設(shè)置只有第一個執(zhí)行的?f?返回結(jié)果能夠設(shè)置成功,其余的被拋棄掉)。而?GetOrSetFuncLock?的緩存方法?f?是在緩存的鎖機制內(nèi)執(zhí)行,因此可以保證當(dāng)緩存項不存在時只會執(zhí)行一次?f?,但是緩存寫鎖的時間隨著?f?方法的執(zhí)行時間而定。

我們來看一個示例:

package main

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gctx"
	"time"
)

func main() {
	var (
		ch    = make(chan struct{}, 0)
		ctx   = gctx.New()
		key   = `key`
		value = `value`
	)
	for i := 0; i < 10; i++ {
		go func(index int) {
			<-ch
			_, err := gcache.GetOrSetFuncLock(ctx, key, func() (interface{}, error) {
				fmt.Println(index, "entered")
				return value, nil
			}, 0)
			if err != nil {
				panic(err)
			}
		}(i)
	}
	close(ch)
	time.Sleep(time.Second)
}

執(zhí)行后,終端輸出(帶有隨機性,但是只會輸出一條信息):

9 entered

可以看到,多個?goroutine?同時調(diào)用?GetOrSetFuncLock?方法時,由于該方法有并發(fā)安全控制,因此最終只有一個?goroutine?的數(shù)值生成函數(shù)執(zhí)行成功,成功之后其他?goroutine?拿到數(shù)據(jù)后則立即返回不再執(zhí)行對應(yīng)的數(shù)值生成函數(shù)。

LRU緩存淘汰控制

package main

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gctx"
	"time"
)

func main() {

	var (
		ctx   = gctx.New()
		cache = gcache.New(2) // 設(shè)置LRU淘汰數(shù)量
	)

	// 添加10個元素,不過期
	for i := 0; i < 10; i++ {
		if err := cache.Set(ctx, i, i, 0); err != nil {
			panic(err)
		}
	}
	size, err := cache.Size(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(size)

	keys, err := cache.Keys(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(keys)

	// 讀取鍵名1,保證該鍵名是優(yōu)先保留
	value, err := cache.Get(ctx, 1)
	if err != nil {
		panic(err)
	}
	fmt.Println(value)

	// 等待一定時間后(默認1秒檢查一次),
	// 元素會被按照從舊到新的順序進行淘汰
	time.Sleep(3 * time.Second)
	size, err = cache.Size(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(size)

	keys, err = cache.Keys(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(keys)
}

執(zhí)行后,輸出結(jié)果為:

10
[2 3 5 6 7 0 1 4 8 9]
1
2
[1 9]

性能測試

測試環(huán)境

CPU: Intel(R) Core(TM) i5-4460  CPU @ 3.20GHz
MEM: 8GB
SYS: Ubuntu 16.04 amd64

測試結(jié)果

john@john-B85M:~/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcache$ go test *.go -bench=".*" -benchmem
goos: linux
goarch: amd64
Benchmark_CacheSet-4                       2000000        897 ns/op      249 B/op        4 allocs/op
Benchmark_CacheGet-4                       5000000        202 ns/op       49 B/op        1 allocs/op
Benchmark_CacheRemove-4                   50000000       35.7 ns/op        0 B/op        0 allocs/op
Benchmark_CacheLruSet-4                    2000000        880 ns/op      399 B/op        4 allocs/op
Benchmark_CacheLruGet-4                    3000000        212 ns/op       33 B/op        1 allocs/op
Benchmark_CacheLruRemove-4                50000000       35.9 ns/op        0 B/op        0 allocs/op
Benchmark_InterfaceMapWithLockSet-4        3000000        477 ns/op       73 B/op        2 allocs/op
Benchmark_InterfaceMapWithLockGet-4       10000000        149 ns/op        0 B/op        0 allocs/op
Benchmark_InterfaceMapWithLockRemove-4    50000000       39.8 ns/op        0 B/op        0 allocs/op
Benchmark_IntMapWithLockWithLockSet-4      5000000        304 ns/op       53 B/op        0 allocs/op
Benchmark_IntMapWithLockGet-4             20000000        164 ns/op        0 B/op        0 allocs/op
Benchmark_IntMapWithLockRemove-4          50000000       33.1 ns/op        0 B/op        0 allocs/op
PASS
ok   command-line-arguments 47.503s

標題名稱:創(chuàng)新互聯(lián)GoFrame教程:GoFrame緩存管理-內(nèi)存緩存
網(wǎng)站路徑:http://www.dlmjj.cn/article/dhojgpc.html