当前位置:网站首页>Go cache of go cache series
Go cache of go cache series
2022-07-02 20:55:00 【firstcode666】
go
Copyright
I'm a lovely groundhog , Focus on sharing Go In the workplace 、 Recruitment and job hunting , Explain Gopher Worry about ! Welcome to follow me .
Welcome aboard Go Recruitment exchange group , Come here to find like-minded friends ! Communicate and learn with marmots .
One sentence description
go-cache [1] Memory based K/V Storage / cache : ( Be similar to Memcached), For stand-alone applications
brief introduction
go-cache What is it? ?
Memory based K/V Storage / cache : ( Be similar to Memcached), For stand-alone applications , Support delete , Be overdue , Default Cache Shared lock ,
A lot of key In this case, lock competition will be serious
Why choose go-cache?
Can store any object ( Store for a given duration or permanently ), And can be composed of multiple goroutine Use cache safely .
Example
package mainimport ("fmt""time""github.com/patrickmn/go-cache")type MyStruct struct {Name string}func main() {// Set timeout and cleanup timec := cache.New(5*time.Minute, 10*time.Minute)// Set the cache value and bring the expiration timec.Set("foo", "bar", cache.DefaultExpiration)// Set no expiration time KEY, This KEY Will not be automatically cleared , Want to clear use :c.Delete("baz")c.Set("baz", 42, cache.NoExpiration)var foo interface{}var found bool// Get valuefoo, found = c.Get("foo")if found {fmt.Println(foo)}var foos string// Get value , And assert thatif x, found := c.Get("foo"); found {foos = x.(string)fmt.Println(foos)}// Operate on the structure pointervar my *MyStructc.Set("foo", &MyStruct{Name: "NameName"}, cache.DefaultExpiration)if x, found := c.Get("foo"); found {my = x.(*MyStruct)// ...}fmt.Println(my)}
Source code analysis
Source code analysis mainly focuses on the core storage structure 、Set、Get、Delete、 Regular cleaning logic for analysis . Including the overall logical architecture
Core storage structure
package cache// Item Each specific cache valuetype Item struct {Object interface{}Expiration int64 // Expiration time : Setup time + Cache time}// Cache Overall cachetype Cache struct {*cache}// cache Overall cachetype cache struct {defaultExpiration time.Duration // Default timeoutitems map[string]Item // KV Yesmu sync.RWMutex // Read-write lock , In operation ( increase , Delete ) Cache withonEvicted func(string, interface{}) // Delete KEY At the time of the CallBack functionjanitor *janitor // Periodically clear the cache structure}// janitor Periodically clear the cache structuretype janitor struct {Interval time.Duration // How often to scan the cachestop chan bool // Whether you need to stop}
Set
package cachefunc (c *cache) Set(k string, x interface{}, d time.Duration) {// "Inlining" of setvar e int64if d == DefaultExpiration {d = c.defaultExpiration}if d > 0 {e = time.Now().Add(d).UnixNano()}c.mu.Lock() // Here you can use defer?c.items[k] = Item{Object: x, // The actual dataExpiration: e, // Next expiration time}c.mu.Unlock()}
Get
package cachefunc (c *cache) Get(k string) (interface{}, bool) {c.mu.RLock() // Lock , Limit concurrent reads and writesitem, found := c.items[k] // stay items This map[string]Item Find dataif !found {c.mu.RUnlock()return nil, false}if item.Expiration > 0 {if time.Now().UnixNano() > item.Expiration { // It's overdue , Go straight back to nil, Why not delete it directly here ?c.mu.RUnlock()return nil, false}}c.mu.RUnlock()return item.Object, true}
Delete
package cache// Delete an item from the cache. Does nothing if the key is not in the cache.func (c *cache) Delete(k string) {c.mu.Lock()v, evicted := c.delete(k)c.mu.Unlock()if evicted {c.onEvicted(k, v) // Delete KEY At the time of the CallBack}}func (c *cache) delete(k string) (interface{}, bool) {if c.onEvicted != nil {if v, found := c.items[k]; found {delete(c.items, k)return v.Object, true}}delete(c.items, k)return nil, false}
Scheduled cleanup logic
package cachefunc newCacheWithJanitor(de time.Duration, ci time.Duration, m map[string]Item) *Cache {c := newCache(de, m)C := &Cache{c}if ci > 0 {runJanitor(c, ci) // Run regularly to clear expired KEYruntime.SetFinalizer(C, stopJanitor) // When C By GC Recovery time , Will stop runJanitor Association in}return C}func runJanitor(c *cache, ci time.Duration) {j := &janitor{Interval: ci,stop: make(chan bool),}c.janitor = jgo j.Run(c) // The new collaboration process does expiration deletion logic}func (j *janitor) Run(c *cache) {ticker := time.NewTicker(j.Interval)for {select {case <-ticker.C: // Every cycle is traversed oncec.DeleteExpired() // Actual deletion logiccase <-j.stop:ticker.Stop()return}}}// Delete all expired items from the cache.func (c *cache) DeleteExpired() {var evictedItems []keyAndValuenow := time.Now().UnixNano()c.mu.Lock()for k, v := range c.items { // Lock and traverse the whole list// "Inlining" of expiredif v.Expiration > 0 && now > v.Expiration {ov, evicted := c.delete(k)if evicted {evictedItems = append(evictedItems, keyAndValue{k, ov})}}}c.mu.Unlock()for _, v := range evictedItems {c.onEvicted(v.key, v.value)}}
reflection
Lock Use
stay go-cache in , It involves reading and writing cache, Basically, locks are used , And the lock is also used when traversing , When cache When the number is very large , When reading and writing frequently , There will be serious lock conflicts .
Use a read-write lock ?
sync.RWMutex, Add RLock, Multiple reads can be allowed . Add Lock, No other reading and writing is allowed .
Whether the granularity of locks can be changed small ?
according to KEY HASH To different map in
Use sync.map?
Reduce the use of locks
runtime.SetFinalizer
In actual programming , We all want to execute a method when each object is released , Perform some counting within this method 、 Release or specific requirements , In the past, the object pointer was set nil Before calling a specific method , golang Provides runtime.SetFinalizer function , When GC When preparing to release objects , The method specified by this function will be called back , Very convenient and effective .
Object can be associated with a SetFinalizer function , When gc detected unreachable Object has an associated SetFinalizer Function time , Will execute the associated SetFinalizer function , At the same time, cancel the Association . So next time gc When , The object is back in unreachable state And there's no SetFinalizer relation , It will be recycled .
Doc
https://pkg.go.dev/github.com/patrickmn/go-cache
Compare
Similar Libraries
https://github.com/golang/groupcache
https://github.com/allegro/bigcache
https://github.com/coocood/freecache
Reference material
[1]
go-cache : https://github.com/patrickmn/go-cache
Data sharing , You can get it by replying to the secret code in the background of official account
【100】Go Resume template of senior engineer
【101 】Go The most complete interview collection in the whole network
【102】Go Super resume
Recommended reading
Welcome to follow me ! Get more information about recruitment .
边栏推荐
- Send blessings on Lantern Festival | limited edition red envelope cover of audio and video is released!
- Makefile: usage of control functions (error, warning, info)
- Jetson XAVIER NX上ResUnet-TensorRT8.2速度與顯存記錄錶(後續不斷補充)
- Research Report on the overall scale, major manufacturers, major regions, products and applications of sliding door dampers in the global market in 2022
- C language linked list -- to be added
- I would like to ask what securities dealers recommend? Is it safe to open a mobile account?
- Sword finger offer (II) -- search in two-dimensional array
- [real case] trap of program design - beware of large data
- Database schema notes - how to choose the right database in development + who invented relational database?
- Write the content into the picture with type or echo and view it with WinHex
猜你喜欢

ROS learning (10): ROS records multiple topic scripts

通信人的经典语录,第一条就扎心了……

数据库模式笔记 --- 如何在开发中选择合适的数据库+关系型数据库是谁发明的?

Second hand housing data analysis and prediction system

Jetson XAVIER NX上ResUnet-TensorRT8.2速度與顯存記錄錶(後續不斷補充)

The first of the classic quotations of correspondents is heartbreaking

Postman接口测试实战,这5个问题你一定要知道

Outsourcing for three years, abandoned

Friends who firmly believe that human memory is stored in macromolecular substances, please take a look
![[internship] solve the problem of too long request parameters](/img/42/413cf867f0cb34eeaf999f654bf02f.png)
[internship] solve the problem of too long request parameters
随机推荐
Codeforces round 651 (Div. 2) (a thinking, B thinking, C game, D dichotomy, e thinking)
Add two numbers of leetcode
Outsourcing for three years, abandoned
Customized Huawei hg8546m restores Huawei's original interface
pytorch 模型保存的完整例子+pytorch 模型保存只保存可训练参数吗?是(+解决方案)
At compilation environment setup -win
mysql
burp 安装 license key not recognized
Why do I have a passion for process?
【实习】解决请求参数过长问题
Data preparation for behavior scorecard modeling
Research Report on the overall scale, major manufacturers, major regions, products and applications of metal oxide arresters in the global market in 2022
想请教一下,究竟有哪些劵商推荐?手机开户是安全么?
ctf-HCTF-Final-Misc200
Research Report on the overall scale, major manufacturers, major regions, products and application segmentation of sound quality head simulators in the global market in 2022
How to open an account online? Is it safe to open a mobile account?
In depth understanding of modern web browsers (I)
C language linked list -- to be added
In the era of consumer Internet, a few head platforms have been born
2021 v+ Quanzhen internet global innovation and Entrepreneurship Challenge, one of the top ten audio and video scene innovation and application pioneers