首页 > 数据库 > > VictoriaMetrics阅读笔记
前言
由于组内搭建了一套VictoriaMtrics(简称为vm)的时序数据存储系统,好奇存储内部是如何实现的,所以打算看下源码,目前在github(https://github.com/VictoriaMetrics/VictoriaMetrics)上有两个版本,一个是单点版本(vminsert,vmstorage,vmselect都是部署在单个节点上的),一个cluster版本(vminsert,vmstorage,vmselect分开部署)。cluster版本要切为cluster分支(原本看单点版本看的一脸懵逼==,好险最后发现其实代码逻辑都是差不多的)
cluster版本的vminsert
vminsert的作用是负责把上游的过来的数据(http)做一些解析/过滤之类的活之后通过rpc把数据发送给vmstorage
cluster版本的vmstorage
vmstorage是负责存储数据的节点,接受vminsert和vmselect的请求,进行存储/查询
因为从vminsert接受的数据里并没有打上TSID之类的信息,所以vmstorage需要先把对应的TSID才能找到对应应该存储的地方。TSID是一条时间序列的唯一标识。TSID的注入会涉及到查询(相同的label的曲线需要有相同的TSID),同时vmstorage为了加速TSID的查找配置了内存缓存等一些加速措施。
type TSID struct {
// 项目和账户,cluster版的vmstorage支持多租户的存储。
AccountID uint32
ProjectID uint32
// 有相同label keys的数据会有相同的MetricGroupID
MetricGroupID uint64
JobID uint32
InstanceID uint32
// 自增ID,这个自增是单节点的自增
MetricID uint64
}
pt.startMergeWorkers()
pt.startRawRowsFlusher()
pt.startInmemoryPartsFlusher()
pt.startStalePartsRemover()tmpBlock.Init(tsid, rrm.auxTimestamps, rrm.auxValues, scale, precisionBits)得到一个实例化的tmpBlock,这个block里面存的timestamp和value都是int64,value是放大后的结果,还存了个scale来表示放大的倍数。rrm.bsw.WriteExternalBlock(说实话,我还没找到这个bsw是在哪实例化的,有点奇怪..)bsw也就是blockstreamwriter。先是更新一波block的原数据,blockOffset、blockSize之类的,然后再把block中的数据序列化为二进制。 type inmemoryPart struct {
ph partHeader
timestampsData bytesutil.ByteBuffer
valuesData bytesutil.ByteBuffer
indexData bytesutil.ByteBuffer
metaindexData bytesutil.ByteBuffer
creationTime uint64
}p, err := mp.NewPart(),有了这个inMemoryPart之后会调用NewPart方法,这个part就是可搜索的part了,这个part因为还只是没有经过merge的part,在vm里面是属于small part,这也是为啥可以看到有small和big两个目录,意思也很简单,一个是用来存小part的,一个是用来存大partmergeSmallParts这个是执行merge part的函数,首先会判断是merge为small part还是big part,然后执行pt.mergeParts(pws, pt.stopCh)。mergeBlockStreamsInternal这个函数里面mergeBlocks这个函数func mergeBlocks(ob, ib1, ib2 *Block, retentionDeadline int64, rowsDeleted *uint64) {
// 最快的路径,block1的最大时间小于block2的最小时间,直接add合并就可以,不用遍历
if ib1.bh.MaxTimestamp < ib2.bh.MinTimestamp {
// Fast path - ib1 values have smaller timestamps than ib2 values.
appendRows(ob, ib1)
appendRows(ob, ib2)
return
}
// 第二种情况,如上
if ib2.bh.MaxTimestamp < ib1.bh.MinTimestamp {
// Fast path - ib2 values have smaller timestamps than ib1 values.
appendRows(ob, ib2)
appendRows(ob, ib1)
return
}
// 这里是用于非法数据的判别
if ib1.nextIdx >= len(ib1.timestamps) {
appendRows(ob, ib2)
return
}
if ib2.nextIdx >= len(ib2.timestamps) {
appendRows(ob, ib1)
return
}
for {
// 这里就是常规的两个有序数组的合并过程
i := ib1.nextIdx
ts2 := ib2.timestamps[ib2.nextIdx]
for i < len(ib1.timestamps) && ib1.timestamps[i] <= ts2 {
i++
}
ob.timestamps = append(ob.timestamps, ib1.timestamps[ib1.nextIdx:i]...)
ob.values = append(ob.values, ib1.values[ib1.nextIdx:i]...)
ib1.nextIdx = i
if ib1.nextIdx >= len(ib1.timestamps) {
appendRows(ob, ib2)
return
}
ib1, ib2 = ib2, ib1
}
}
优点
缺点
https://zhuanlan.zhihu.com/p/394961301
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69999831/viewspace-3123269/ ,如需转载,请注明出处,否则将追究法律责任。