当前位置:首页 > 数码 > b-Go-成功线程安保的缓存-sync.Map-中经常使用-b

b-Go-成功线程安保的缓存-sync.Map-中经常使用-b

admin8个月前 (04-30)数码34

缓存是提升现代运行程序性能的关键方面。它准许您存储并极速检索低廉操作的结果或经常访问的数据,缩小了重复从新计算或失掉数据的须要。在本文中,咱们将讨论如何经常使用sync.Map包在Go中成功线程安保的缓存。这种缓存成功支持缓存条目的过时,确保过时的数据不会滞留在缓存中。

为什么要费神

在咱们开局成功自己的线程安保内存缓存之前,让咱们思索一下其优缺陷。思索到代替打算是经常使用为缓存而发明的、有常年经常使用和支持历史的外部库(工具),让咱们思索一下优势和缺陷。

经常使用Go的sync.Map成功自己的线程安保缓存相比经常使用像这样的外部库有几个优势,这取决于您的用例和要求。以下是经常使用sync.Map创立自己的缓存或许有优势的一些要素:

然而,值得留意的是,经常使用像Redis这样的外部缓存处置打算关于较大规模的运行程序或那些有更复杂的缓存需求的运行程序有其自身的一系列优势。经常使用Redis的一些好处包含:

最终,选用经常使用sync.Map成功自己的缓存还是经常使用像Redis这样的外部库将取决于您的详细需求、运行程序的规模以及您在性能、复杂性和资源方面情愿做的掂量。

此外,成功您的缓存会带来乐趣并协助更好地理解像Redis这样的更复杂的产品。因此,咱们将在此文章中成功一个。

为什么咱们经常使用sync.Map

便捷地说,由于它完美地满足了咱们的须要。更深化的解释-sync.Map是Go规范库中的一个并发的、线程安保的map成功。它设计用于在多个goroutine并发访问映射的状况下经常使用,并且键的数量是未知的或随期间变动的。

值得留意的是,只管sync.Map是特定用例的一个很好的选用,但它并不象征着要交流一切场景的内置map类型。特意是,sync.Map最适宜以下状况:

在键的数量是固定的或事前知道的状况下,且映射可以预先调配,经常使用适当的同步如sync.Mutex或sync.RWMutex的内置map类型或许会提供更好的性能。

创立SafeCache

如上所述,咱们的SafeCache是一个便捷的、线程安保的缓存,经常使用Go的sync.Map存储其键值对。

首先,咱们定义一个CacheEntry结构来保管值及其过时期间戳:

typeCacheEntrystruct{valueinterface{}expirationint64}

在SafeCache结构中嵌入了一个sync.Map,它提供了对键值对的并发安保访问:

typeSafeCachestruct{syncMapsync.Map}

向缓存中增加值

而后咱们定义了一个Set方法,该方法准许咱们在缓存中存储一个带有指定生活期间(TTL,TimeToLive)的值。TTL选择了缓存条目应被以为有效的期间长度。一旦TTL过时,在下一个清算周期中将会移除该缓存条目。

func(sc*SafeCache)Set(keystring,valueinterface{},ttltime.Duration){expiration:=time.Now().Add(ttl).UnixNano()sc.syncMap.Store(key,CacheEntry{value:value,expiration:expiration})}

从缓存中检索值

接上去须要的方法是Get,它经常使用键从缓存中检索值。假设没有找到该值或该值已过时,该方法将前往false:

func(sc*SafeCache)Get(keystring)(interface{},bool){//...(seetheprovidedcodeforthefullimplementation)}

在Get方法中关键的是从缓存加载值后启动类型断言。咱们依赖于sync.Map的Load方法,该方法前往接口。

entry,found:=sc.syncMap.Load(key)if!found{returnnil,false}//TypeassertiontoCacheEntry,asentryisaninterface{}cacheEntry:=entry.(CacheEntry)

从缓存中移除值

当然,咱们还须要一个Delete方法,使咱们能够从缓存中移除一个值:

func(sc*SafeCache)Delete(keystring){sc.syncMap.Delete(key)}

清算过时条目

咱们经过CleanUp方法裁减了缓存,该方法担任活期从缓存中删除过时的条目。它经常使用sync.Map提供的Range方法遍历缓存中的一切键值对,并删除那些TTL已过时的条目:

func(sc*SafeCache)CleanUp(){//...(seetheprovidedcodeforthefullimplementation)}

要运转CleanUp方法,咱们可以在初始化缓存时启动一个独自的Goroutine:

cache:=&SafeCache{}gocache.CleanUp()

完整的代码片段

packagecacheimport("sync""time")//CacheEntryisavaluestoredinthecache.typeCacheEntrystruct{valueinterface{}expirationint64}//SafeCacheisathread-safecache.typeSafeCachestruct{syncMapsync.Map}//SetstoresavalueinthecachewithagivenTTL//(timetolive)inseconds.func(sc*SafeCache)Set(keystring,valueinterface{},ttltime.Duration){expiration:=time.Now().Add(ttl).UnixNano()sc.syncMap.Store(key,CacheEntry{value:value,expiration:expiration})}//Getretrievesavaluefromthecache.Ifthevalueisnotfound//orhasexpired,itreturnsfalse.func(sc*SafeCache)Get(keystring)(interface{},bool){entry,found:=sc.syncMap.Load(key)if!found{returnnil,false}//TypeassertiontoCacheEntry,asentryisaninterface{}cacheEntry:=entry.(CacheEntry)iftime.Now().UnixNano()>cacheEntry.expiration{sc.syncMap.Delete(key)returnnil,false}returncacheEntry.value,true}//Deleteremovesavaluefromthecache.func(sc*SafeCache)Delete(keystring){sc.syncMap.Delete(key)}//CleanUpperiodicallyremovesexpiredentriesfromthecache.func(sc*SafeCache)CleanUp(){for{time.Sleep(1*time.Minute)sc.syncMap.Range(func(key,entryinterface{})bool{cacheEntry:=entry.(CacheEntry)iftime.Now().UnixNano()>cacheEntry.expiration{sc.syncMap.Delete(key)}returntrue})}}

最后,你可以运转以下的mn.go程序来审核缓存能否上班。咱们创立了一个HTTP主机,它在/compute端点监听恳求。该主机接受一个整数n作为查问参数,并前往低廉计算的结果(在这种状况下,带有模拟提前的便捷平方操作)。主机首先审核缓存,看看给定输入的结果能否曾经被缓存;假设没有,它会计算结果,将其存储在缓存中,并将其前往给客户端。

要测试主机,运转代码并恳求。第一个恳求会破费更长的期间(由于模拟的提前),但具备相反n的后续恳求将立刻前往缓存的结果。

packagemainimport("fmt""log""/http""safe-cache/cache""strconv""time")funcexpensiveComputation(nint)int{//Simulateanexpensivecomputationtime.Sleep(2*time.Second)returnn*n}funcmain(){safeCache:=&cache.SafeCache{}//StartagoroutinetoperiodicallycleanupthecachegosafeCache.CleanUp()http.HandleFunc("/compute",func(whttp.ResponseWriter,r*http.Request){query:=r.URL.Query()n,err:=strconv.Atoi(query.Get("n"))iferr!=nil{http.Error(w,"Invalidinput",http.StatusBadRequest)return}cacheKey:=fmt.Sprintf("result_%d",n)cachedResult,found:=safeCache.Get(cacheKey)varresultintiffound{result=cachedResult.(int)}else{result=expensiveComputation(n)safeCache.Set(cacheKey,result,1*time.Minute)}_,err=fmt.Fprintf(w,"Result:%dn",result)iferr!=nil{return}})log.Fatal(http.ListenAndServe(":8080",nil))}

论断

在本文中,咱们展现了如何经常使用sync.Map包在Go中成功一个便捷、线程安保的缓存。

这个缓存成功支持基于TTL的过时的键值存储,并可以轻松地集成到你的Go运行中,以提高性能并缩小对你的数据源或计算资源的负载。


linux sync和sync使用哪个

不是windows中的保存 为了提高磁盘的读写效率,linux 会把频繁读写的磁盘文件在内存中做缓存。 。 但是这会造成数据的不同步, sync 就是为了数据同步。 。 (flush file system buffers)

C#程序运行时出现异常System.Runtime.InteropServices.COMException (0x80040154)

成功线程安保的缓存

当安装中缺失非托管同步组件(如 )时,发生此异常.当卸载了 Sync Framework 或安装未成功完成时,可能发生此问题.解决办法重新安装 Sync Framework.

免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。

标签: Go

“b-Go-成功线程安保的缓存-sync.Map-中经常使用-b” 的相关文章

中-Goroutines-成功轻量级并发的高效并发原语-Go

中-Goroutines-成功轻量级并发的高效并发原语-Go

并发是现代软件开发的一个基本概念,使程序能够同时口头多个义务。在Go编程畛域,了解Goroutines是至关关键的。本文将片面概述Goroutines,它们的轻量级特性,如何经常使用go关键字创立...

Templ-编写-Go-用户界面-HTML-如何在-中经常使用 (temple)

Templ-编写-Go-用户界面-HTML-如何在-中经常使用 (temple)

简介 templ[1]是一个在Go中编写用户界面的言语。经常使用templ,咱们可以创立可出现HTML片段的组件,并将它们组合起来创立屏幕、页面、文档或运行程序。 装置 咱们可以...

在-使用-应用-中构建高性能-Echo-Web-Go (在使用应急法压缩时间时,不一定)

在-使用-应用-中构建高性能-Echo-Web-Go (在使用应急法压缩时间时,不一定)

Echo是一个高性能且易用的框架,用于构建Go语言编写的Web应用。它具备灵活的路由功能、方便的请求处理、强大的中间件支持和简单的JSON操作,非常适合快速开发API服务和Web应用。 快速...

etcd-的依赖问题最终得到解决-Go (etcd的英文全称)

etcd-的依赖问题最终得到解决-Go (etcd的英文全称)

几年前,我经常接触到一组微服务相关组件:gRPC、gRPC 网关、etcd、Protobuf 和 protoc-gen-go。一开始,它们都能很好地协同工作,并且随着新版本的发布而持续更新。...

Go-内存调配优化-在结构体中充沛应用内存 (go 内存)

Go-内存调配优化-在结构体中充沛应用内存 (go 内存)

在经常使用Golang启动内存调配时,咱们须要遵照一系列规定。在深化了解这些规定之前,咱们须要先了解变量的对齐形式。 Golang的unsafe包中有一个函数Alignof,签名如下: f...

内存优化与渣滓搜集-深化探求优化程序性能的最佳通常-Go (内存优化与渣子有关吗)

内存优化与渣滓搜集-深化探求优化程序性能的最佳通常-Go (内存优化与渣子有关吗)

Go提供了智能化的内存治理机制,但在某些状况下须要更精细的微调从而防止出现OOM失误。本文将讨论Go的渣滓搜集器、运行程序内存优化以及如何防止OOM(Out-Of-Memory)失误。 Go...

内存效率-多用途-语言中使用切片代替数组的优点-动态大小-Go (内存使用效率)

内存效率-多用途-语言中使用切片代替数组的优点-动态大小-Go (内存使用效率)

引言 在 Go 语言中,数组是一种固定长度的数据结构,而切片则是一种可变长度的数据结构。虽然数组和切片都可以存储相同类型的数据元素,但切片在使用上有其独到的优势,本文将通过介绍切片的特性来解释为...

14条超乎想象的Go接口最佳实践

14条超乎想象的Go接口最佳实践

近年来,越来越多的开发者开始关注 Go 语言,它以其高效、简洁和高并发性而闻名。在 Go 语言中,接口是一个非常强大的特性,它可以帮助我们定义和实现不同的行为。本文将介绍 Go 语言中接口设计的一...