【VictoriaMetrics源码阅读】: vm中对map的优化


作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!

  • cnblogs博客
  • zhihu
  • github
  • 公众号:一本正经的瞎扯

具体代码请看:https://github.com/ahfuzhang/victoria-metrics-1.72.0/blob/master/VictoriaMetrics-1.72.0-cluster/lib/storage/storage.go#L2219

在并发环境下的map,第一想到的就是sync.Map,但是在读多写少的情况下,sync.Map的查询性能不如map;且,sync.Map的内存结构更加复杂,不便于准确的控制总内存量。

于是VM中应用了这样一些技巧来避免使用synv.Map:

  1. 对象中使用了两个map,分为mutable可变和immutale不可变;
  2. 查询的时候,先不加锁查询immutable,如果查询不到,再加锁查询mutable;
  3. 写入数据的时候,加锁写入mutable;
  4. 查询的时候触发mutable到immutable的迁移:
    • 内部记录一个下次迁移时间,默认是10秒;也就是最短10秒才会触发mutable到immutable的搬迁;(业务场景允许)
    • 搬迁的时候,把immutable写入到mutable,然后把当前的mutable作为immutable
      • 为什么不是把mutable的数据写入immutable呢?因为immutable是读不加锁的,为了实现这部分查询的无锁,只能搬迁到新对象上去。
  5. 有时候,某个KEY的查询会非常频繁。因此会把最后一次命中的value写到额外的成员变量。查询的时候优先判断key是否是上次查询的key,如果是就直接返回缓存的value。这是某种意义的分支预测技术!