【张润涛 源码】【徐州溯源码】【文雅源码公式】freecache源码分析

1.鹅厂微创新Golang缓存组件TCache介绍
2.浅谈Golang两种线程安全的码分map

freecache源码分析

鹅厂微创新Golang缓存组件TCache介绍

       一个 Golang 自研小组件,TCache 介绍

       作者:frank、码分maxy、码分lark 等。码分

       TCache 是码分一个 Golang 团队自研的缓存组件,旨在优化视频会员场景下高并发请求的码分张润涛 源码压力,减少底层存储压力,码分提升系统可用性。码分设计时,码分我们考虑了开源组件如布隆过滤器、码分位图、码分localcache 的码分特点和优劣,以业务需求为出发点,码分集成这些组件形成整体解决方案。码分

       TCache 设计目标

       主要目标是码分为视频会员服务提供高效缓存,应对大量 APP 请求,减轻存储层压力,并增强系统稳定性。经过调研,我们发现现有开源组件适合不同场景,徐州溯源码因此决定整合这些组件,通过配置化设计,让业务根据自身需求选择合适的缓存策略。

       整体架构

       TCache 分为四层架构:业务场景层、中间件层、组件层与算法层。业务场景层直接与应用交互,中间件层集成了多种缓存算法,组件层基于开源组件实现,算法层则深入研究缓存技术原理。

       组件结构

       TCache 集成了多种缓存组件,包括 KV 型结构 Cache、BitMap、BloomFilter 与大型计数器 Hyperloglog。此外,我们计划集成更多组件以覆盖更多业务场景。

       Cache 组件设计

       提供了统一的 cache 接口,支持用户自定义底层缓存实现,包括默认实现与本地缓存组件 localcache 的文雅源码公式接口定义。

       BitMap 组件设计

       BitMap 组件集成经典 BitMap 与 Roaring 位图算法,提供单一操作 API,便于业务集成使用。组件结构清晰,代码接口明确。

       开发过程

       TCache 的开发过程始于团队转型 Golang 时的技术积累与开源组件分析,通过源码阅读、论文研读,深入了解组件技术,最终形成组件化设计。团队持续研究缓存替换算法、位图算法,通过实验对比分析,提炼出业务适用的缓存策略。

       功能分析

       本地缓存强调数据一致性与吞吐量,支持多线程访问与内存限制,适用于缓存热点数据。常见组件如 freecache、fastcache、pda app源码bigcache 等,提供线程安全、高命中率与高效管理的特性。

       源码分析

       深入研究开源组件,如 BigCache、BloomFilter、RoaringBitmap,通过建模与代码分析,了解组件实现原理与优化策略。

       算法研究

       研究缓存替换算法,包括 Belady 最优策略、随机策略、先进先出、最近不使用、最不经常使用、重引用间隔预测等。通过实验对比分析,提炼出适用于不同场景的缓存策略。

       实验研究

       通过功能与性能对比研究,lutter项目源码推荐不同缓存组件在特定场景下的应用,如 freecache、bigcache、fastcache、localcache 等,以及针对数据持久化与热启动的组件。

       组件化

       整合多种组件形成 TCache,通过组件化设计,让业务灵活选择缓存策略,提高系统性能与稳定性。

       总结

       TCache 的开发是一个无心插柳的成果,整合了团队的技术积累与业务需求。通过研究、实验与优化,我们找到了适合视频会员服务的缓存解决方案。未来,结合 AIGC 等新技术,开发出更多原创组件,有可能推动开发行业的变革。

浅谈Golang两种线程安全的map

       文章标题:浅谈Golang两种线程安全的map

       导语:本文将深入探讨Golang中的本地缓存库选择与对比,帮助您解决困惑。

       Golang map并发读写测试:

       在Golang中,原生的map在并发场景下的读写操作是线程不安全的,无论key是否相同。具体来说,当并发读写map的不同key时,运行结果会出现并发错误,因为map在读取时会检查hashWriting标志。如果存在该标志,即表示正在写入,此时会报错。在写入时,会设置该标志:h.flags |= hashWriting。设置完成后,系统会取消该标记。

       使用-race编译选项可以检测并发问题,这是通过Golang的源码分析、文章解析和官方博客中详细解释的。

       map+读写锁实现:

       在官方sync.map库推出之前,推荐使用map与读写锁(RWLock)的组合。通过定义一个匿名结构体变量,包含map、RWLock,可以实现读写操作。

       具体操作方法如下:从counter中读取数据,往counter中写入数据。然而,sync.map和这种实现方式有何不同?它在性能优化方面做了哪些改进?

       sync.map实现:

       sync.map使用读写分离策略,通过空间换取时间,优化了并发性能。相较于map+RWLock的实现,它在某些特定场景中减少锁竞争的可能性,因为可以无锁访问read map,并优先操作read map。如果仅操作read map即可满足需求(如增删改查和遍历),则无需操作write map,后者在读写时需要加锁。

       sync.map的源码深入分析:

       接下来,我们将着重探讨sync.Map的源码,以理解其运作原理,包括结构体Map、readOnly、entry等。

       sync.Map方法介绍:

       sync.Map提供了四个关键方法:Store、Load、Delete、Range。具体功能如下:

       Load方法:解释Map.dirty如何提升为Map.read的机制。

       Store方法:介绍tryStore函数、unexpungeLocked函数和dirtyLocked函数的实现。

       Delete方法:简单总结。

       Range方法:简单总结。

       sync.Map总结:

       sync.Map更适用于读取频率远高于更新频率的场景(appendOnly模式,尤其是key存一次,多次读取且不删除的情况),因为在key存在的情况下,读写删操作可以无锁直接访问readOnly。不建议用于频繁插入与读取新值的场景,因为这会导致dirty频繁操作,需要频繁加锁和更新read。此时,github开源库orcaman/concurrent-map可能更为合适。

       设计点:expunged:

       expunged是entry.p值的三种状态之一。当使用Store方法插入新key时,会加锁访问dirty,并将readOnly中未被标记为删除的所有entry指针复制到dirty。此时,之前被Delete方法标记为软删除的entry(entry.p被置为nil)都会变为expunged状态。

       sync.map其他问题:

       sync.map为何不实现len方法?这可能涉及成本与收益的权衡。

       orcaman/concurrent-map的适用场景与实现:

       orcaman/concurrent-map适用于反复插入与读取新值的场景。其实现思路是对Golang原生map进行分片加锁,降低锁粒度,从而达到最少的锁等待时间(锁冲突)。

       它实现简单,部分源码如下,包括数据结构和函数介绍。

       后续:

       在其他业务场景中,可能需要本地kv缓存组件库,支持键过期时间设置、淘汰策略、存储优化、GC优化等功能。此时,可能需要了解freecache、gocache、fastcache、bigcache、groupcache等组件库。

       参考链接:

       链接1:/questions//golang-fatal-error-concurrent-map-read-and-map-write/

       链接2:/golang/go/issues/

       链接3:/golang/go/blob/master/src/sync/map.go

       链接4:/orcaman/concurrent-map

更多内容请点击【综合】专栏