关于golang:GO-语言-JSON-与-Cache-库-调研与选型

39次阅读

共计 3643 个字符,预计需要花费 10 分钟才能阅读完成。

JSON

基本上从以下两种角度进行剖析

  1. 性能方面,如是否应用反射;
  2. 是否反对 Unmarshal 到 map 或 struct,未波及灵活性与扩展性方面,上面报告中只思考最简略的反序列化,不会提及每个库的灵活性,如提供的一些定制化抽取的 API;

相干库

GO 1.14 规范库 JSON
大量应用反射获取值,首先 go 的反射自身性能较差,其次频繁调配对象,也会带来内存调配和 GC 的开销;

valyala/fastjson star: 1.4k

  1. 通过遍历 json 字符串找到 key 所对应的 value,返回其值 []byte,由业务方自行处理。同时能够返回一个 parse 对象用于屡次解析;
  2. 只提供了简略的 get 接口,不提供 Unmarshal 到构造体或 map 的接口;

tidwall/gjson star: 9.5k

  1. 原理与 fastjson 相似,但不会像 fastjson 一样将解析的内容保留在一个 parse 对象中,后续能够重复的利用,所以当调用 GetMany 想要返回多个值的时候,须要遍历 JSON 串屡次,因而效率会比拟低;
  2. 提供了 get 接口和 Unmarshal 到 map 的接口,但没有提供 Unmarshal 到 struct 的接口;

buger/jsonparser star: 4.4k

  1. 原理与 gjson 相似,有一些更灵便的 api;
  2. 只提供了简略的 get 接口,不提供 Unmarshal 到构造体或 map 的接口;

json-iterator star: 10.3k

  1. 兼容规范库;
  2. 其之所以快,一个是尽量减少不必要的内存复制,另一个是缩小 reflect 的应用——同一类型的对象,jsoniter 只调用 reflect 解析一次之后即缓存下来。
  3. 不过随着 go 版本的迭代,原生 json 库的性能也越来越高,jsonter 的性能劣势也越来越窄, 但仍有显著劣势

sonic star: 2k

  1. 兼容规范库;
  2. 通过 JIT(即时编译)和 SIMD(单指令 - 多数据)减速;
    须要 go 1.15 及以上的版本,提供实现的 json 操作的 API,是一个比 json-iterator 更优的抉择。
  3. 曾经在抖音外部大范畴应用,且 github 库保护给力,issues 解决踊跃,安全性有保障。
  4. 具体介绍

easyjson star: 3.5k

  1. 反对序列化和反序列化;
  2. 通过代码生成的形式,达到不应用反射的目标;

相干压测数据可见参考文章;

选型案例

业务场景

  1. 须要 Unmarshal map;
  2. json 导致的 GC 与 CPU 压力较大;
  3. 业务较为重要,须要一个稳固的序列化库;

选型思路

  1. easyjson 须要生成代码,丢失了 json 的灵活性,减少保护老本,因而不予考虑;
  2. sonic 须要 go 1.15 及以上的版本,且业务场景无 Unmarshal 到构造体的操作,因而临时不做抉择;
  3. json-iterator 的劣势在于兼容规范库接口,但因为应用到了反射,性能绝对较差,且业务场景没有反序列化构造体的场景,因而不予考虑;
  4. fastjson、gjson、jsonparser 因为没有用到反射,因而性能要高于 json-iterator。所以着重在这三个中抉择;
  5. fastjson 实现了 0 调配的开销,然而 star 数较少,不予考虑;
  6. gjson 与 jsonparser 相似,速度及内存调配上各擅胜场,灵活性上也各有短处,比拟难抉择,但业务场景下不须要应用到其提供的灵便 API,而有 json 序列化到 map 的场景,所以 gjson 会有一些劣势,再联合 star 数后抉择 gjson;

论断

综上所述,选用 gjson。

参考

https://www.luozhiyun.com/arc…
https://segmentfault.com/a/11…

Cache

基本上从以下四种角度进行剖析

  1. GC 方面,是否有针对性优化;
  2. 是否须要限度内存大小,如果限度,命中率与淘汰策略如何;
  3. TTL 反对水平:全局、单个 key、不反对;
  4. 其余个性;

此处因业务场景起因未具体探讨淘汰策略方面,但这是本地缓存中一个较为重要的局部;
各 cache 的命中率,能够看文章的命中率报告局部;
但正如《A large scale analysis of hundreds of in-memory cache clusters at Twitter》论文所提到,Under reasonable cache sizes, FIFO often shows similar performance as LRU, and LRU often exhibits advantages only when the cache size is severely limited. 因而在本地缓存的场景下,淘汰策略的抉择对于缓存命中率的影响当较为重要;

相干库

go-cache star: 5.7k

  1. 最简略的 cache,能够间接存储指针,上面的局部 Cache 都须要先把对象序列化为 []byte,会引入肯定的序列化开销,但能够用高效的序列化库缩小开销;
  2. 能够对每个 key 设置 TTL;
  3. 无淘汰机制;

freecache star: 3.6k

  1. 0 GC;
  2. 能够对每个 key 设置 TTL;
  3. 近 LRU 淘汰;
  4. 参考资料

bigcache star: 5.4k

  1. 0 GC;
  2. 只有全局 TTL,不能对每个 key 设置 TTL;
  3. 如果超过内存最大值(也能够不设置,内存应用无下限),采纳的是 FIFO 策略;
  4. 产生 hash 抵触会导致旧值被笼罩;
  5. 会在内存中调配大数组用以达到 0 GC 的目标,肯定水平上会影响到 GC 频率;
  6. 参考资料

fastcache star: 1.3k

  1. 0 GC;
  2. 不反对 TTL;
  3. 如果超过设置最大值,底层是 ring buffer,缓存会被笼罩掉,采纳的是 FIFO 策略;
  4. 调用 mmap 调配堆外内存,因而不会影响到 gc 频率;
  5. 参考资料

groupcache star: 11k

  1. 一个较为简单的 cache 实现,实质上是个 LRU cache;
  2. 是一个 lib 库模式的过程内的分布式缓存,也能够认为是本地缓存,但不是简略的单机缓存,不过也能够作为单机缓存;
  3. 参考资料
  4. 个性如下:
    单机缓存和基于 HTTP 的分布式缓存;
    最近起码拜访(LRU,Least Recently Used)缓存策略;
    应用 Golang 锁机制避免缓存击穿;
    应用一致性哈希抉择节点以实现负载平衡;
    应用 Protobuf 优化节点间二进制通信;

goburrow star: 468

  1. Go 中 Guava Cache 的局部实现;
  2. 没有对 GC 做优化,外部应用 sync.map;
  3. 反对淘汰策略:LRU、Segmented LRU (default)、TinyLFU (experimental);

ristretto star: 3.6k

  1. 在 GC 方面做了大量优化;
  2. 能够对每个 key 设置 TTL;
  3. 在吞吐方面做了较多优化,使得在简单的淘汰策略下仍具备较好的吞吐程度;
  4. 在命中率方面,具备杰出的准入政策和 SampledLFU 驱赶政策,因而高于其余 cache 库;
  5. 参考资料

选型案例

业务场景 – Feature 服务

  1. key 分钟固定窗口生效,且 key 中自带分钟级工夫戳;
  2. 内存容量足够,有全局 TTL 即可,不须要额定的淘汰机制;
  3. 缓存 Key 数量较多,对 GC 压力较大;
  4. Value 是 string,另外能够通过不平安形式无开销转换为 []byte;
  5. 业务较为重要,须要一个稳固的 cache 库;

选型思路

  1. goburrow、ristretto 两个 cache 的主打的是固定内存状况下的命中率,对 GC 无优化,且 Feature 服务的 Cache 是分钟固定窗口生效,机器内存容量远大于窗口内的缓存 value 之和,因而不须要用到更好的淘汰机制,而且 Feature 服务本次更换 cahce 要解决的是缓存中对象数量太多,导致的 GC 问题,因而不思考这两种;
  2. groupcache 是一个 LRU Cache,且性能较重,Feature 服务只须要一个本地 Cache 库,不须要用到这些个性,因而不思考这个 Cahce;
  3. fastcache 最大的问题是不反对 TTL,这个是 Feature 服务所不能承受的,因而不思考这个 Cahce;
  4. go-cache 相似于 Feature 服务中的 beego/cache 库,最简略的 Cache 库,对 GC 无优化,且 Feature 服务的 value 自身就为 string 类型,不会引入序列化开销,且能够通过不平安的形式实现 string 与 []byte 之间 0 开销转换;
  5. freecache、bigcache 比拟适宜 Feature 服务,freecache 的劣势在于近 LRU 的淘汰,并且能够对每个 Key 设置 TTL,但 Feature 服务内存空间足够无需进行缓存淘汰,且 key 名中自带分钟级工夫戳,key 有效期都为 1min,因而无需应用 freecache;
  6. bigcache 绝对于 freecache 的劣势之一是您不须要提前晓得缓存的大小,因为当 bigcache 已满时,它能够为新条目调配额定的内存,而不是像 freecache 以后那样笼罩现有的。摘自:https://github.com/allegro/bi…

论断

综上所述,bigcache 的序列化开销、无奈为每个 key 设置 TTL、缓存淘汰效率差与命中率低等问题 Feature 服务都能够优雅防止,所以 bigcache 最适宜作为以后场景下的本地 Cache。

正文完
 0