教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Golang缓存生态

Golang缓存生态

发布时间:2022-02-03   编辑:jiaochengji.com
教程集为您提供Golang缓存生态等资源,欢迎您收藏本站,我们将为您提供最新的Golang缓存生态资源

前言

这篇专注讲golang的缓存生态,把github上golang缓存比较好的项目集中起来分析一下,也算是给之后的发展打补丁。

<h2>一 golang缓存现状</h2>

缓存框架的必备要求:

1.支持并发

合理运用锁,什么时候加锁什么时候解锁,防止脏数据;又要防止死锁活锁资源占用

合理运用golang sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁)

2.支持内存限制 ( 限制最大的可使用空间 )

怎么去设定缓存参数使得缓存的内存限制得到有效的控制。涉及到golang gc,缓存要对内存实际使用量做限制,内存激增同样会导致资源竞争问题。

Go 请求内存很容易,但释放给操作系统却很难。当碎片被清空的同时,goroutines 去访问 key 的时候,会开始分配内存空间,此时之前的内存空间并没有被完全释放,这导致内存的激增,甚至会出发 OOM 错误。
而且缓存访问的模式还受 Zipf 定律的束缚。最常访问的几个 key 仍然存在几个锁,因此产生 Goroutines 的竞争问题。这种方式不满足多核之间的扩展的需求。

3.缓存扩展问题

在多核和多 Goroutines 之间更好的扩展

单机使用,或者只有一个请求者连续请求的情况下,缓存做到资源管理。多核多goroutine就会涉及到缓存动态扩展问题,业务量上来了怎么去迁移数据保证请求的资源最大限度发挥效用,往往会用到缓存分片

在非随机密钥的情况下,很好地扩展 (eg. Zipf)

齐夫定律可以表述为:在自然语言的语料库里,一个单词出现的频率与它在频率表里的排名成反比。所以,频率最高的单词出现的频率大约是出现频率第二位的单词的2倍,而出现频率第二位的单词则是出现频率第四位的单词的2倍。这个定律被作为任何与幂定律概率分布有关的事物的参考。搜索引擎经常用到这个定律。缓存这里可以想为zipf定律下如何合理分配缓存的key使得频率访问次数科学地使用缓存。

4.更高的缓存命中率

由于内存速度比磁盘读写速度快很多,我们当然希望所有的请求热点数据都打到缓存上,充分利用内存以及CPU资源做到效益最大化

 

<h2>二 golang缓存流行种类</h2>


go-cache
安装方法:go get github.com/patrickmn/go-cache
是一个运行在单机上的k/v缓存,相当于memcached,实现线程安全,可以带有过期时间访问清理。里面有cache和sharded cache两种,而且加入了单测可以去看怎么去使用,value支持有限的数据类型不过可扩展,是一个比较老的实现,go-cache实质上就是拥有过期时间并且线程安全的map,可以被多个goroutine安全访问。当成一个简单可用的demo是可以好的。

 

FreeCache - A cache library for Go with zero GC overhead and high concurrent performance.

https://github.com/coocood/freecache.git
0gc过剩,支持高并发,支持lru,支持过期清理get,严格限制内存使用量,同时具有审计平均access时间,hitcount等功能,现在仍有活跃开发

FreeCache 将缓存分成了 256 段,每段包括 256 个槽和一个 ring buffer 存储数据。set数据使用 hash 值下 8 位作为标识 id,通过使用 LSB 9-16 的值作为槽 ID。将数据分配到多个槽里面,有助于优化查询的时间 ( 分治策略 )。

数据被存储在 每个槽的ring buffer 中,相当于一个排序的数组里面。如果 ring buffer 内存不足,则会利用 LRU 的策略在 ring buffer 逐个扫描,如果缓存的最后访问时间小于平均访问的时间,就会被删掉。要找到一个缓存内容,在槽中是通过二分查找法对一个已经排好的数据进行查询。

 

BIGCache

https://github.com/allegro/bigcache.git

支持分片支持时间控制,支持最大cache空间限制,支持verbose开关 使用读写锁RWMUTEX读锁无消耗
参数如下,是个全面可控的golang cache

Shards
CleanWindow
MaxEntriesInWindow
MaxEntrySize
Verbose
HardMaxCacheSize
OnRemove
OnRemoveWithReason
BigCache 会通过 Hash 的方式进行分片。 每个分片都包含一个 map 和一个 ring buffer。无论如何添加元素,都会将它放置在对应的 ring buffer 中,并将位置保存在 map 中。如果多次设置相同的元素,则 ring buffer 中的旧值则会被标记为无效,如果 ring buffer 太小,则会进行扩容。

每个 map 的 key 都是一个 uint32 的 hash 值,每个值对应一个存储着元数据的 ring buffer。如果 hash 值碰撞了,BigCache 会忽略旧 key,然后把新的值存储到 map 中。预先分配更少,更大的 ring buffer,使用 map [uint32] uint32 是避免支付 GC 扫描成本的好方法

BigCache 不能有效地利用缓冲区,并且可能会在缓冲区中为同一个键存储多个条目。
BigCache 不更新访问 ( 读 ) 条目,因此会导致最近访问的键被删除

 

GroupCache

https://github.com/golang/groupcache.git
星标最多的cache 支持shardByKey,P2P形式形成一个分布式缓存,更好的cachefilling,得益于p2p,cache不命中时只需要在其中的某个cache添加data即可,同时抛弃版本号的概念并支持把super-hot key备份到所有节点

GroupCache 使用链表和 Map 实现了一个精准的 LRU 删除策略的缓存。为了进行公平的比较,我们在 GroupCache 的基础上,实现了一个包括 256 个分片的切片结构。

 

参考资料:

1. HS 缓存设计:http://highscalability.com/blog/2016/1/25/design-of-a-modern-cache.html

2. golang缓存现状:https://studygolang.com/articles/19402

到此这篇关于“Golang缓存生态”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Golang缓存生态
php页面静态化的小例子
php Smarty的缓存操作
CodeIgniter框架中启用和清除缓存的教程
修改dedecms 织梦系统 生成静态页面栏目缓存文件路径
php页面缓存的例子(减经cpu与mysql负担)
[译]如果对齐内存的写入是原子性的,为什么我们还需要sync/atomic包
golang锁记
有关php的缓存技术介绍
解析 PHP和浏览器缓存机制

[关闭]
~ ~