当前位置:网站首页>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 .
边栏推荐
- JS modularization
- 疫情封控65天,我的居家办公心得分享 | 社区征文
- This team with billions of data access and open source dreams is waiting for you to join
- 【Hot100】21. Merge two ordered linked lists
- 通信人的经典语录,第一条就扎心了……
- 【实习】解决请求参数过长问题
- Google Earth engine (GEE) - Landsat 9 image full band image download (Beijing as an example)
- After eight years of test experience and interview with 28K company, hematemesis sorted out high-frequency interview questions and answers
- 2021 software security report: open source code, happiness and disaster depend on each other?
- [question brushing diary] classic questions of dynamic planning
猜你喜欢
![[871. Minimum refueling times]](/img/5f/75e717d1fc9d1c5f9e1d8f59dda38c.png)
[871. Minimum refueling times]

Interested parties add me for private chat

pytorch 模型保存的完整例子+pytorch 模型保存只保存可训练参数吗?是(+解决方案)

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

Basic concept of database, installation and configuration of database, basic use of MySQL, operation of database in the project

C language linked list -- to be added

【实习】解决请求参数过长问题

Add two numbers of leetcode

Redis sentinel cluster working principle and architecture deployment # yyds dry goods inventory #

Burp install license key not recognized
随机推荐
【QT】QPushButton创建
数据库模式笔记 --- 如何在开发中选择合适的数据库+关系型数据库是谁发明的?
功能、作用、效能、功用、效用、功效
Cron expression (seven subexpressions)
Redis -- three special data types
想请教一下,究竟有哪些劵商推荐?手机开户是安全么?
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
Research Report on the overall scale, major manufacturers, major regions, products and applications of battery control units in the global market in 2022
ROS learning (10): ROS records multiple topic scripts
At compilation environment setup -win
After eight years of test experience and interview with 28K company, hematemesis sorted out high-frequency interview questions and answers
[cloud native topic -50]:kubesphere cloud Governance - operation - step by step deployment of microservice based business applications - database middleware MySQL microservice deployment process
Data preparation for behavior scorecard modeling
I would like to ask what securities dealers recommend? Is it safe to open a mobile account?
Research Report on the overall scale, major manufacturers, major regions, products and applications of metal oxide arresters in the global market in 2022
Volvo's first MPV is exposed! Comfortable and safe, equipped with 2.0T plug-in mixing system, it is worth first-class
疫情封控65天,我的居家办公心得分享 | 社区征文
[fluent] dart generic (generic class | generic method | generic with specific type constraints)
在券商账户上买基金安全吗?哪里可以买基金
2021 software security report: open source code, happiness and disaster depend on each other?