在实际业务中这样一个需求,部署在某台机器上的程序,维护有一个id,这个id在程序内部每次收到请求时会 + 1,当程序崩溃重启时需要知道重启前的这个id值,这样当重启时就知道id应该取什么初始值了。这很明显是一个读少写多的场景。想到的方法有两种,一个是利用redis进行缓存,因为只需要维护一个id,并不需要很大的内存;一个是本地缓存,一个是按照文件进行维护,一个是按照共享内存维护。
起初使用了redis维护,想着方便。但是在测试中发现,会出现一些dail timeout的情况,想着并不稳妥,所以决定本地维护一个文件,在程序重启时open文件,在程序退出前close,类似于写日志一样。
因为文件里其实只是一个数字,所以在读的时候需要seek一下,在写的时候需要seek后truncate一下
Seekfunc (f *File) Seek(offset int64, whence int) (ret int64, err error)
官方注释:Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。
Truncatefunc (f *File) Truncate(size int64) error
官方注释:Truncate改变文件的大小,对文件进行截断,它不会改变I/O的当前位置。 如果截断文件,多出的部分就会被丢弃。如果出错,错误底层类型是*PathError。
实现// 读
func Get() (string, error) {
// 读需要从头开始,所以设置距离文件头0字节
// Seek是设置下一次读写的位置
F.Seek(0, 0)
id, err := ioutil.ReadAll(F)
if err != nil {
return "", err
}
// 避免末尾是一个'\n'
if id[len(id)-1] == '\n' {
return string(id[:len(id)-1]), nil
}
return string(id), nil
}
// 写
func Set(id string) error {
// 写需要从头开始写并覆盖
F.Seek(0, 0)
F.Truncate(0)
_, err := F.Write([]byte(id))
return err
}
本地共享内存的demo以后再更
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)