当前位置:网站首页>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 .
边栏推荐
- Research Report on the overall scale, major manufacturers, major regions, products and application segmentation of shock absorber oil in the global market in 2022
- 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
- What is online account opening? Is it safe to open an account online now?
- Postman interface test practice, these five questions you must know
- [fluent] dart function (function composition | private function | anonymous function | function summary)
- 【Hot100】23. Merge K ascending linked lists
- CRM Customer Relationship Management System
- 【Kubernetes系列】kubeadm reset初始化前后空间、内存使用情况对比
- Analyze comp-206 advanced UNIX utils
- Interpretation of some papers published by Tencent multimedia laboratory in 2021
猜你喜欢

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

CRM Customer Relationship Management System

Detailed upgrade process of AWS eks

Talk about macromolecule coding theory and Lao Wang's fallacy from the perspective of evolution theory

Interested parties add me for private chat

Database schema notes - how to choose the right database in development + who invented relational database?

Outsourcing for three years, abandoned

Roommate, a king of time, I took care of the C language structure memory alignment

CS5268完美代替AG9321MCQ Typec多合一扩展坞方案

B-end e-commerce - reverse order process
随机推荐
[hands on deep learning]02 softmax regression
Talk about macromolecule coding theory and Lao Wang's fallacy from the perspective of evolution theory
The first of the classic quotations of correspondents is heartbreaking
Don't you want to have a face-to-face communication with cloud native and open source experts? (including benefits
【871. 最低加油次数】
Sweet talk generator, regular greeting email machine... Open source programmers pay too much for this Valentine's day
Customized Huawei hg8546m restores Huawei's original interface
【Hot100】21. 合并两个有序链表
[12] the water of the waves is clear, which can wash my tassel. The water of the waves is muddy, which can wash my feet
Internal/validators js:124 throw new ERR_ INVALID_ ARG_ Type (name, 'string', value) -- solution
Interpretation of some papers published by Tencent multimedia laboratory in 2021
想请教一下,我在东莞,到哪里开户比较好?手机开户是安全么?
Automated video production
Research Report on the overall scale, major manufacturers, major regions, products and applications of micro hydraulic cylinders in the global market in 2022
Want to ask, is there any discount for opening an account now? Is it safe to open an account online?
Research Report on the overall scale, major manufacturers, major regions, products and application segmentation of the inverted front fork of the global market in 2022
Codeforces Round #771 (Div. 2)(A-C)
Friends who firmly believe that human memory is stored in macromolecular substances, please take a look
Common routines of compressed packets in CTF
[871. Minimum refueling times]