[[Xtsdb]]のデータ階層化方式で,系列のカーディナリティが高いときに,系列の長さが規定量に届く前に[[notes/system-engineering/Redis]]のメモリ使用量が頭打ちになることがある。こういうときどうするかなあ。Redisのmaxmemoryあたりのメモリ使用率をgoroutineで定期的に監視して、閾値を超えたらSCANでキーをなめて、レコードサイズが大きいものを削除していくとかだろうか。レコードサイズが大きいキーをどうやって知るか。ランダムなカーソルでSCANしてえたサンプルレコード群に対して、現在のメモリ使用率のパーセンタイル値をフラッシュするレコードサイズの閾値とするとかかなあ。そのあと閾値をもとに改めて全レコードをSCANして、閾値を超えているキーを削除していく。SCANする間にメモリ使用率を参照しつづけて、メモリ使用率が増加しつづけるようであれば、goroutineを増やして削除スピードをあげる。メモリ使用率を一定に保つための制御にPID制御器とかが使えそう。
あるいは現在のメモリ使用率とキーの個数をもとに、系列単位の上限バイト数を動的に変更し続けるとか。
XtsdbのなぜかRedis上のデータを削除できていない問題に取り組んだ。
どうもRedisのPub/Subが安定していないようにみえる。TTL以外に
XtsdbのTTL値がまれにおかしな値になってRedisに怒られる。
```go
package main
import (
"fmt"
"hash/fnv"
"math"
)
func getMetricID(metricName string) uint64 {
h := fnv.New64a()
h.Write([]byte(metricName))
return h.Sum64()
}
func main() {
var eseconds float64 = 1800.0
name := "cpu.usage_user;{hostname=host_0;}region=ap-northeast-1;datacenter=ap-northeast-1a;rack=72;os=Ubuntu16.10;arch=x86;team=CHI;service=10;service_version=0;service_environment=test; "
id := getMetricID(name)
ttlf := eseconds + math.Mod(math.Float64frombits(id), eseconds)
fmt.Println(math.Float64bits(ttlf))
}
```
[https://play.golang.org/p/4Kru5M-knap](https://play.golang.org/p/4Kru5M-knap)