作为我要建立的文档数据库系统模块的一部分,我已经构建了一个简单的数据存储。
为了可靠地存储数据,我必须遵守ACID属性。以下是我的保存方法。
func (document Document) Save() (hash string, err error) {
if err := os.MkdirAll(document.FileDirectory(), 0600); err != nil {
return "", err
}
file, err := os.Create(document.TmpFile())
if err != nil {
return "", err
}
file.Write(document.Data)
if err := file.Sync(); err != nil {
return "", err
}
file.Close()
if err := os.Rename(document.TmpFile(), document.File()); err != nil {
return "", err
}
return document.Hash(), nil
}
首先,数据(以 []byte 格式)被保存到一个临时文件中。然后使用 file.Sync()
将文件与持久存储同步,以确保数据被写入持久存储。接下来将临时文件重命名为新文件名。
注意:
我选择的存储数据文件的方式是 spoolDir 格式。这意味着从数据生成的哈希的前两个字符用作父目录名称,后面两个字符用作后续目录名称。文件名将是剩下的 36 个字符。临时文件只有一个后缀 .tmp
,文件路径和文件名相同。这种设计的灵感来自于 git
存储数据的方式。
问题: 我实现的数据存储算法是否足以确保数据可靠地持久化。
迄今为止的答案: 关于目录同步以确保数据耐久性的一些内容(我不确定)。
提前致谢
按照 rightfold 建议更新的代码:
func (document Document) Save() (hash string, err error) {
if err := os.MkdirAll(document.FileDirectory(), 0600); err != nil {
return "", err
}
file, err := os.Create(document.TmpFile())
if err != nil {
return "", err
}
file.Write(document.Data)
if err := file.Sync(); err != nil {
return "", err
}
file.Close()
if err := os.Rename(document.TmpFile(), document.File()); err != nil {
os.Remove(document.TmpFile())
return "", err
}
return document.Hash(), nil
}
document.File()
存在,os.Rename()
将返回一个错误。而在其他操作系统上,它会很好地替换它。 - zserge