godis
godis copied to clipboard
support eviction
support lfu and lru
Eviction 这边有几个问题:
- runtime.ReadMemStats 需要 StopTheWorld, 成本极高
- 对象可能已经不再使用但仍未 GC
- 不确定需要逐出多少对象
我后来考虑了一下可以这样解决:
- 首先使用 gopsutil 从操作系统中获取当前进程内存占用。它的成本很低不会影响正常运行。
- 若 gopsutil 发现内存超限手动调用 runtime.GC 优先进行垃圾回收
- 垃圾回收后使用 runtime.ReadMemStats 再次检查内存,若仍超限再进行逐出
- 设置一个逐出的 batch size,再逐出一批对象后再次调用 runtime.GC 和 runtime.ReadMemStats 直到内存符合要求:
伪代码
func eviction() {
if gopsutil.RSS < maxMemory {
return
}
for i:=0; i < loopLimit; i++ { // go 的 gc 不一定立即完成,还是设个上限
runtime.GC()
if runtime.ReadMemStats < maxMemory {
return
}
const batchSize = 1024
evict(batchSize)
}
}
另外 :
- EvictionPolicy 的几个 public 函数和 db.Eviction() 是没有注释的,麻烦按照 go lint 的要求加一下注释.
- GetMaxMemoryState 直接返回 memToFree 就好,不用传指针进去
- db.Eviction() 在主协程调用太消耗性能了,开一个 cron 吧
这个属性在gc后,并没有减少
这个属性在gc后,并没有减少
info中
Eviction 这边有几个问题:
- runtime.ReadMemStats 需要 StopTheWorld, 成本极高
- 对象可能已经不再使用但仍未 GC
- 不确定需要逐出多少对象
我后来考虑了一下可以这样解决:
- 首先使用 gopsutil 从操作系统中获取当前进程内存占用。它的成本很低不会影响正常运行。
- 若 gopsutil 发现内存超限手动调用 runtime.GC 优先进行垃圾回收
- 垃圾回收后使用 runtime.ReadMemStats 再次检查内存,若仍超限再进行逐出
- 设置一个逐出的 batch size,再逐出一批对象后再次调用 runtime.GC 和 runtime.ReadMemStats 直到内存符合要求:
伪代码
func eviction() { if gopsutil.RSS < maxMemory { return } for i:=0; i < loopLimit; i++ { // go 的 gc 不一定立即完成,还是设个上限 runtime.GC() if runtime.ReadMemStats < maxMemory { return } const batchSize = 1024 evict(batchSize) } }另外 :
- EvictionPolicy 的几个 public 函数和 db.Eviction() 是没有注释的,麻烦按照 go lint 的要求加一下注释.
- GetMaxMemoryState 直接返回 memToFree 就好,不用传指针进去
- db.Eviction() 在主协程调用太消耗性能了,开一个 cron 吧
info中,有数据的属性只用rss和vms似乎都不符合
RSS 是物理内存大小, VMS 是虚拟内存空间大小,这里当然使用 RSS.
GC 后内存读数未减少的原因很复杂,比如 runtime.GC 不一定立即完成清理、回收的内存不一定立即还给操作系统。 runtime.GC() 后再次检查内存使用 runtime.ReadMemStat 而不用系统的 RSS 就是为了拿到尽可能实时的内存占用量。
我做了一些实验,总的来说由于 GC 和操作系统内存管理的各种机制存在很难拿到准确的内存使用量, eviction 只能尽力而为吧
RSS 是物理内存大小, VMS 是虚拟内存空间大小,这里当然使用 RSS.
GC 后内存读数未减少的原因很复杂,比如 runtime.GC 不一定立即完成清理、回收的内存不一定立即还给操作系统。 runtime.GC() 后再次检查内存使用 runtime.ReadMemStat 而不用系统的 RSS 就是为了拿到尽可能实时的内存占用量。
我做了一些实验,总的来说由于 GC 和操作系统内存管理的各种机制存在很难拿到准确的内存使用量, eviction 只能尽力而为吧
如果这样的话,很容易下一次检查的时候发现内存超出限制,但是实际上已经腾出了内存,只能延长时间间隔,难搞
改用定时任务的话,就需要遍历 所有的(16个)db实例,也会消耗性能吧,
如果这样的话,很容易下一次检查的时候发现内存超出限制 这事我之前还没考虑过,只能每次 eviction 之后一段时间内暂停 OOM 检测。
放到定时任务里是为了保证线上快速响应命令,每次执行命令都要查一下RSS会导致命令执行非常非常慢,定时任务不会影响命令执行速度。

这个属性在gc后,并没有减少