当前位置: 首页 > news >正文

企网站建设网站嵌入播放器

企网站建设,网站嵌入播放器,成都软件培训机构排名前十,如何开一个微信公众号本文主要介绍go语言中本地缓存的使用#xff0c;首先由简单到复杂手写3个本地缓存示例#xff0c;使用内置的sync#xff0c;map等数据结构封装cache#xff0c;然后介绍常见的一些开源库#xff0c;以及对比常用的开源库 文章目录 前言手写本地缓存CacheNormalCacheExCac… 本文主要介绍go语言中本地缓存的使用首先由简单到复杂手写3个本地缓存示例使用内置的syncmap等数据结构封装cache然后介绍常见的一些开源库以及对比常用的开源库 文章目录 前言手写本地缓存CacheNormalCacheExCacheV3 开源库cache2gogo-cachebigcachegroupcache本地缓存对比 前言 本地缓存是指将一部分数据存储在应用程序本地内存中以提高数据访问速度和应用程序性能的技术。 使用本地缓存的优势 提高应用程序性能减少网络延迟改善用户体验降低外部存储系统的负荷 下面我们从简单到复杂写本地缓存 手写本地缓存 CacheNormal 在 Go 中你可以使用内置的 sync 包和 map 数据结构来实现本地缓存。 我们首先定义了一个名为 Cache 的结构体其中包含一个 data 字段它是一个 map[string]interface{} 类型的数据结构用于存储键值对。我们使用 sync.RWMutex 来保证并发安全性。 然后我们定义了 Set 方法和 Get 方法用于设置和获取缓存值。在 Set 方法中我们使用互斥锁 mu 来保证并发安全。在 Get 方法中我们使用读写锁 mu 的读锁来实现并发读取。 package cacheimport (sync )type CacheNormal struct {data map[string]interface{}mu sync.RWMutex }func NewCache() *CacheNormal {return CacheNormal{data: make(map[string]interface{}),} }func (c *CacheNormal) Set(key string, value interface{}) {c.mu.Lock()defer c.mu.Unlock()c.data[key] value }func (c *CacheNormal) Get(key string) (interface{}, bool) {c.mu.RLock()defer c.mu.RUnlock()value, ok : c.data[key]return value, ok } 代码测试 package cacheimport (fmttestingtime )func TestCacheNorm(t *testing.T) {cache : NewCache()// 设置缓存值cache.Set(key1, value1)cache.Set(key2, value2)// 读取缓存值value1, ok1 : cache.Get(key1)fmt.Println(Key1:, value1, ok1)value2, ok2 : cache.Get(key2)fmt.Println(Key2:, value2, ok2)// 等待一段时间time.Sleep(5 * time.Second)// 再次读取缓存值value1, ok1 cache.Get(key1)fmt.Println(Key1:, value1, ok1)value2, ok2 cache.Get(key2)fmt.Println(Key2:, value2, ok2) }结果展示 下面我们实现一个带有过期时间的本地缓存。 CacheEx 要实现带有过期时间的本地缓存可以使用 Go 的 sync 包和 map 数据结构结合定时器time.Timer来实现。 我们定义了一个名为 CacheEx 的结构体其中包含了一个用于存储缓存项的 data 字段并且还有一个用于接收过期键的通道 expireCh。 通过调用 NewCacheEx 函数创建一个新的缓存对象该函数会启动一个协程 startCleanup 来定期清理过期的缓存项。 使用 Set 方法来设置缓存值并指定缓存项的过期时间。在这个方法中我们使用互斥锁来保证并发安全性并将缓存项的过期时间和值存储在 data 中。同时我们还使用 scheduleExpiration 方法来安排过期时的清理操作。 使用 Get 方法来获取缓存值。在这个方法中我们使用读锁来进行并发读取并检查缓存项是否过期。如果缓存项存在且未过期则返回对应的值否则返回空值。 package cacheimport (synctime )type CacheEx struct {data map[string]cacheItemmu sync.RWMutexexpireCh chan string }type cacheItem struct {value interface{}expiration time.Time }func NewCacheEx() *CacheEx {c : CacheEx{data: make(map[string]cacheItem),expireCh: make(chan string),}go c.startCleanup()return c }func (c *CacheEx) Set(key string, value interface{}, expiration time.Duration) {c.mu.Lock()defer c.mu.Unlock()expireTime : time.Now().Add(expiration)c.data[key] cacheItem{value: value,expiration: expireTime,}go c.scheduleExpiration(key, expireTime) }func (c *CacheEx) Get(key string) (interface{}, bool) {c.mu.RLock()defer c.mu.RUnlock()item, ok : c.data[key]if ok item.expiration.After(time.Now()) {return item.value, true}return nil, false }func (c *CacheEx) Delete(key string) {c.mu.Lock()defer c.mu.Unlock()delete(c.data, key) }func (c *CacheEx) startCleanup() {for {key : -c.expireChc.Delete(key)} }func (c *CacheEx) scheduleExpiration(key string, expireTime time.Time) {duration : time.Until(expireTime)timer : time.NewTimer(duration)-timer.Cc.expireCh - key }代码测试 func TestCacheExpireTime(t *testing.T) {cache : NewCacheEx()// 设置缓存值带有过期时间cache.Set(key1, value1, 2*time.Second)cache.Set(key2, value2, 5*time.Second)// 读取缓存值value1, ok1 : cache.Get(key1)fmt.Println(Key1:, value1, ok1)value2, ok2 : cache.Get(key2)fmt.Println(Key2:, value2, ok2)// 等待一段时间time.Sleep(3 * time.Second)// 再次读取缓存值value1, ok1 cache.Get(key1)fmt.Println(Key1:, value1, ok1)value2, ok2 cache.Get(key2)fmt.Println(Key2:, value2, ok2) }结果展示 CacheV3 package cacheimport (synctime )type item struct {value interface{}expiration int64 }type CacheV3 struct {items sync.Maplock sync.RWMutexdefaultTTL time.DurationmaxCapacity intevictList []interface{} }func NewCacheV3(defaultTTL time.Duration, maxCapacity int) *CacheV3 {return CacheV3{defaultTTL: defaultTTL,maxCapacity: maxCapacity,evictList: make([]interface{}, 0, maxCapacity),} }func (c *CacheV3) Set(key string, value interface{}, ttl time.Duration) {c.lock.Lock()defer c.lock.Unlock()if c.cacheSize() c.maxCapacity {c.evict(1)}if ttl 0 {ttl c.defaultTTL}expiration : time.Now().Add(ttl).UnixNano()c.items.Store(key, item{value, expiration})time.AfterFunc(ttl, func() {c.lock.Lock()defer c.lock.Unlock()if _, found : c.items.Load(key); found {c.items.Delete(key)c.evictList append(c.evictList, key)}}) }func (c *CacheV3) Get(key string) (interface{}, bool) {c.lock.RLock()defer c.lock.RUnlock()if val, found : c.items.Load(key); found {item : val.(*item)if item.expiration 0 time.Now().UnixNano() item.expiration {c.items.Delete(key)return nil, false}return item.value, true}return nil, false }func (c *CacheV3) evict(count int) {for i : 0; i count; i {key : c.evictList[0]c.evictList c.evictList[1:]c.items.Delete(key)} }func (c *CacheV3) cacheSize() int {size : 0c.items.Range(func(_, _ interface{}) bool {sizereturn true})return size }代码测试 func TestCacheV3(t *testing.T) {c : NewCacheV3(time.Minute, 100)c.Set(key1, value1, time.Second*30)c.Set(key2, value2, time.Minute)val, found : c.Get(key1)if found {fmt.Println(val)}time.Sleep(time.Second * 45)val, found c.Get(key1)if found {fmt.Println(val)}time.Sleep(time.Second * 30)val, found c.Get(key1)if found {fmt.Println(val)} else {fmt.Println(key1 expired)} }结果展示 开源库 cache2go 最新代码请参考https://github.com/muesli/cache2go 以下代码仅供参考 type Item struct {//read write locksync.RWMutexkey interface{}data interface{}// cache duration.duration time.Duration// create timecreateTime time.Time//last access timeaccessTime time.Time//visit timescount int64// callback after deletingdeleteCallback func(key interface{}) }//create item. func NewItem(key interface{}, duration time.Duration, data interface{}) *Item {t : time.Now()return Item{key: key,duration: duration,createTime: t,accessTime: t,count: 0,deleteCallback: nil,data: data,} }//keep alive func (item *Item) KeepAlive() {item.Lock()defer item.Unlock()item.accessTime time.Now()item.count }func (item *Item) Duration() time.Duration {return item.duration }func (item *Item) AccessTime() time.Time {item.RLock()defer item.RUnlock()return item.accessTime }func (item *Item) CreateTime() time.Time {return item.createTime }func (item *Item) Count() int64 {item.RLock()defer item.RUnlock()return item.count }func (item *Item) Key() interface{} {return item.key }func (item *Item) Data() interface{} {return item.data }func (item *Item) SetDeleteCallback(f func(interface{})) {item.Lock()defer item.Unlock()item.deleteCallback f }// table for managing cache items type Table struct {sync.RWMutex//all cache itemsitems map[interface{}]*Item// trigger cleanupcleanupTimer *time.Timer// cleanup intervalcleanupInterval time.DurationloadData func(key interface{}, args ...interface{}) *Item// callback after adding.addedCallback func(item *Item)// callback after deletingdeleteCallback func(item *Item) }func (table *Table) Count() int {table.RLock()defer table.RUnlock()return len(table.items) }func (table *Table) Foreach(trans func(key interface{}, item *Item)) {table.RLock()defer table.RUnlock()for k, v : range table.items {trans(k, v)} }func (table *Table) SetDataLoader(f func(interface{}, ...interface{}) *Item) {table.Lock()defer table.Unlock()table.loadData f }func (table *Table) SetAddedCallback(f func(*Item)) {table.Lock()defer table.Unlock()table.addedCallback f }func (table *Table) SetDeleteCallback(f func(*Item)) {table.Lock()defer table.Unlock()table.deleteCallback f }func (table *Table) RunWithRecovery(f func()) {defer func() {if err : recover(); err ! nil {fmt.Printf(occur error %v \r\n, err)}}()f() }func (table *Table) checkExpire() {table.Lock()if table.cleanupTimer ! nil {table.cleanupTimer.Stop()}if table.cleanupInterval 0 {table.log(Expiration check triggered after %v for table, table.cleanupInterval)} else {table.log(Expiration check installed for table)}// in order to not take the lock. use temp items.items : table.itemstable.Unlock()//in order to make timer more precise, update now every loop.now : time.Now()smallestDuration : 0 * time.Secondfor key, item : range items {//take out our things, in order not to take the lock.item.RLock()duration : item.durationaccessTime : item.accessTimeitem.RUnlock()// 0 means valid.if duration 0 {continue}if now.Sub(accessTime) duration {//cache item expired._, e : table.Delete(key)if e ! nil {table.log(occur error while deleting %v, e.Error())}} else {//find the most possible expire item.if smallestDuration 0 || duration-now.Sub(accessTime) smallestDuration {smallestDuration duration - now.Sub(accessTime)}}}//trigger next cleantable.Lock()table.cleanupInterval smallestDurationif smallestDuration 0 {table.cleanupTimer time.AfterFunc(smallestDuration, func() {go table.RunWithRecovery(table.checkExpire)})}table.Unlock() }// add item func (table *Table) Add(key interface{}, duration time.Duration, data interface{}) *Item {item : NewItem(key, duration, data)table.Lock()table.log(Adding item with key %v and lifespan of %d to table, key, duration)table.items[key] itemexpDur : table.cleanupIntervaladdedItem : table.addedCallbacktable.Unlock()if addedItem ! nil {addedItem(item)}//find the most possible expire item.if duration 0 (expDur 0 || duration expDur) {table.checkExpire()}return item }func (table *Table) Delete(key interface{}) (*Item, error) {table.RLock()r, ok : table.items[key]if !ok {table.RUnlock()return nil, errors.New(fmt.Sprintf(no item with key %s, key))}deleteCallback : table.deleteCallbacktable.RUnlock()if deleteCallback ! nil {deleteCallback(r)}r.RLock()defer r.RUnlock()if r.deleteCallback ! nil {r.deleteCallback(key)}table.Lock()defer table.Unlock()table.log(Deleting item with key %v created on %s and hit %d times from table, key, r.createTime, r.count)delete(table.items, key)return r, nil }//check exist. func (table *Table) Exists(key interface{}) bool {table.RLock()defer table.RUnlock()_, ok : table.items[key]return ok }//if exist, return false. if not exist add a key and return true. func (table *Table) NotFoundAdd(key interface{}, lifeSpan time.Duration, data interface{}) bool {table.Lock()if _, ok : table.items[key]; ok {table.Unlock()return false}item : NewItem(key, lifeSpan, data)table.log(Adding item with key %v and lifespan of %d to table, key, lifeSpan)table.items[key] itemexpDur : table.cleanupIntervaladdedItem : table.addedCallbacktable.Unlock()if addedItem ! nil {addedItem(item)}if lifeSpan 0 (expDur 0 || lifeSpan expDur) {table.checkExpire()}return true }func (table *Table) Value(key interface{}, args ...interface{}) (*Item, error) {table.RLock()r, ok : table.items[key]loadData : table.loadDatatable.RUnlock()if ok {//update visit count and visit time.r.KeepAlive()return r, nil}if loadData ! nil {item : loadData(key, args...)if item ! nil {table.Add(key, item.duration, item.data)return item, nil}return nil, errors.New(cannot load item)}return nil, nil }// truncate a table. func (table *Table) Truncate() {table.Lock()defer table.Unlock()table.log(Truncate table)table.items make(map[interface{}]*Item)table.cleanupInterval 0if table.cleanupTimer ! nil {table.cleanupTimer.Stop()} }//support table sort type ItemPair struct {Key interface{}AccessCount int64 }type ItemPairList []ItemPairfunc (p ItemPairList) Swap(i, j int) { p[i], p[j] p[j], p[i] } func (p ItemPairList) Len() int { return len(p) } func (p ItemPairList) Less(i, j int) bool { return p[i].AccessCount p[j].AccessCount }//return most visited. func (table *Table) MostAccessed(count int64) []*Item {table.RLock()defer table.RUnlock()p : make(ItemPairList, len(table.items))i : 0for k, v : range table.items {p[i] ItemPair{k, v.count}i}sort.Sort(p)var r []*Itemc : int64(0)for _, v : range p {if c count {break}item, ok : table.items[v.Key]if ok {r append(r, item)}c}return r }// print log. func (table *Table) log(format string, v ...interface{}) {//fmt.Printf(format\r\n, v) }func NewTable() *Table {return Table{items: make(map[interface{}]*Item),} }go-cache https://github.com/patrickmn/go-cache 优点 简单易用适合快速集成到现有项目中。支持过期时间可以自动淘汰过期的缓存项。支持多种数据类型的缓存。 缺点 性能略低于其他库不适合高并发读写的场景。不支持分布式缓存。 bigcache https://github.com/allegro/bigcache 优点 高性能适用于需要快速读写大量数据的场景。使用murmurhash算法来计算哈希值减少了哈希冲突。使用多个shard来减少锁竞争。 缺点 不支持过期时间只能手动清除过期的缓存项。内存使用较高不适合存储大量数据。 groupcache https://github.com/golang/groupcache 优点 支持分布式缓存可以在多台机器上共享缓存。采用LRU算法来淘汰缓存项具备一定的缓存性能。提供一致性哈希算法可以解决节点扩容等问题。 缺点 比较复杂使用起来较为繁琐。只支持字符串类型的键值对。 本地缓存对比 参考文档 https://zhuanlan.zhihu.com/p/487455942 https://www.jianshu.com/p/0ff2e8c61c9c?tdsourcetags_pctim_aiomsg 下面对每个库的详细介绍 go-cache 描述go-cache是一款简单而有效的内存缓存库支持设置过期时间和GC机制。并发安全是使用Go的sync.Map实现数据的并发安全存储和访问。存储限制无可以存储任意类型的数据。淘汰策略默认为LRU最近最少使用算法也支持手动删除过期的缓存项。分布式支持不支持。 freecache 描述freecache是一款高性能的内存缓存库使用LRU算法进行缓存项的淘汰。并发安全是使用读写锁实现并发安全访问。存储限制固定大小需要在初始化时指定总共可以缓存的字节数。淘汰策略默认为LRU最近最少使用算法不支持自定义。分布式支持不支持。 bigcache 描述bigcache是一款高性能的内存缓存库使用murmurhash哈希算法快速查找。并发安全是使用多个读写锁来实现高并发的访问控制。存储限制固定大小需要在初始化时指定最多可以缓存的条目数。淘汰策略默认为LRU最近最少使用算法不支持自定义。分布式支持不支持。 groupcache 描述groupcache是一款支持分布式缓存的库提供一致性哈希和HTTP请求缓存功能。并发安全是使用读写锁实现并发安全访问。存储限制无可以存储任意类型的数据。淘汰策略支持自定义淘汰策略例如手动删除过期的缓存项。分布式支持是支持分布式缓存将数据分片存储在多个节点上通过查询一致性哈希环来确定数据所在的节点。 gocache 描述gocache是一款快速、强大的内存缓存库支持过期时间、并发安全和自定义淘汰策略。并发安全是使用读写锁实现并发安全访问。存储限制无可以存储任意类型的数据。淘汰策略默认为LRU最近最少使用算法也支持自定义淘汰策略。分布式支持不支持。
http://www.zqtcl.cn/news/449191/

相关文章:

  • 一般做哪些外贸网站丰南建设局网站
  • 网站如何被收录情况自己做的网站如何实现下载文件
  • 龙岩网站设计一般要多久深圳做自适应网站设计
  • 类似于拼多多的网站怎么做资料下载网站建设
  • 做商城网站哪里网站官网建设的价格
  • 网站怎么做用户体验山东富国建设投资有限公司网站
  • app ui模板网站首页改版影响优化
  • 周村网站制作哪家好网站设计基本要素
  • 网站制作与维护费用wordpress文章页不显示侧边
  • 嘉兴网站建设正规公司做室内设计人喜欢的网站
  • 入侵dedecms网站管理员密码百度注册域名免费建站
  • 找晚上做的工作去哪个网站企业开发软件公司拓展方案
  • 济宁建站公司wordpress博客入门
  • 做外贸需要网站wordpress app 打包
  • 免费网站站长查询丽水微信网站建设公司
  • 广州品牌网站建设先做网站 先备案
  • jsp系统网站建设带源代码梧州网页设计
  • 二手书籍交易网站开发方式关键词seo排名优化如何
  • 陕西西安潍坊网站seo外包
  • 计算机专业网站开发开题报告网站推广营销怎么做
  • 比较大的做网站的公司电影网站盗链怎么做
  • 江苏响应式网站建设哪里有台州网站制作方案
  • 深圳设计网站有哪些展览展会策划公司
  • 微信生活门户网站源码河北建设厅网站初始密码
  • 企业如何做网站推广成都外贸网站建设
  • 网页设计 网站建设 哪个好佛山网站建设推广服务
  • 东莞网站建设技术支持产品推广怎么写
  • 银川app购物网站制作公司网站建设怎样提升形象与品牌价值
  • 中山城市建设集团网站信誉好的邯郸网站建设
  • 做网站很赚钱吗贵阳网站建设费用