在GoLang中编写可靠的数据存储

时间:2014-03-22 04:00:21

标签: git database-design go

我一直在构建一个简单的数据存储,作为我的文档数据库系统模块的一部分,我将为教育目的而构建。

为了可靠地存储数据,我必须遵守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
}

首先将数据(以[]字节为单位)保存到临时文件中。然后,该文件与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
}

1 个答案:

答案 0 :(得分:4)

您正在做的事情保证了OS和硬件保证的程度(这是您能获得的最佳程度)。

它也是原子的;不完整的写入不会留下不完整的数据,即使CPU发生火灾。

重命名失败时,您可能希望删除临时文件:

if err := os.Rename(document.TmpFile(), document.File()); err != nil {
    os.Remove(document.TmpFile()) // ignore errors
    return "", err
}