如何确保NoSQL记录中属性的唯一性(Golang + tiedot)

时间:2016-10-15 22:15:53

标签: go unique tiedot nosql

我正在研究一个用golang编写的简单应用程序,使用tiedot作为NoSQL数据库引擎。 我需要将一些用户存储在数据库中。

type User struct {
    Login        string
    PasswordHash string
    Salt         string
}

当然,两个用户不能拥有相同的登录名,并且 - 由于此引擎不提供任何事务机制 - 我想知道如何确保在编写时数据库中没有重复登录。

我首先想到的是,我可以在插入之前通过登录搜索用户,但是数据库将是 使用得很清楚,它不可靠。

也许我可以等待一个随机时间,如果该集合中有另一个用户具有相同的登录名,则将其删除,但这听起来也不可靠。

这是否可行,或者我应该切换到支持事务的数据库引擎吗?

2 个答案:

答案 0 :(得分:2)

以下是我的解决方案。它不是Tiedot特有的,但它使用CQRS并且可以应用于各种DB。

您还可以使用它来获得其他好处,例如缓存和批量写入(如果DB支持它),以防止在每次请求时询问DB。

package main

import (
    "sync"
    "log"
    "errors"
)

type User struct {
    Login        string
    PasswordHash string
    Salt         string
}

type MutexedUser struct {
    sync.RWMutex
    Map map[string]User
}

var u = &MutexedUser{}

func main() {
    var user User

    u.Sync()
    // Get new user here
    //...
    if err := u.Insert(user); err != nil {
        // Ask to provide new login
        //...
        log.Println(err)
    }
}

func (u *MutexedUser) Insert(user User) (err error) {
    u.Lock()
    if _, ok := u.Map[user.Login]; !ok {
        u.Map[user.Login] = user
        // Add user to DB
        //...
        u.Unlock()
        return err
    }
    u.Unlock()
    return errors.New("duplicated login")
}

func (u *MutexedUser) Read(login string) User {
    u.RLock()
    value := u.Map[login]
    u.RUnlock()

    return value
}

func (u *MutexedUser) Sync() (err error) {
    var users []User

    u.Lock()
    defer u.Unlock()
    // Read users from DB
    //...
    u.Map = make(map[string]User)
    for _, user := range users {
        u.Map[user.Login] = user
    }
    return err
}

答案 1 :(得分:1)

  

我首先想到的是,我可以在插入之前通过登录搜索用户,但由于数据库将被使用,因此它不可靠。

对,它会造成竞争条件。解决此问题的唯一方法是:

  1. 锁定表格
  2. 搜索登录
  3. 如果未找到登录信息,则插入
  4. 解锁表格
  5. 表锁不是可扩展的解决方案,因为它会在您的应用程序中造成昂贵的瓶颈。这就是为什么像MySQL的MyISAM这样的非事务性存储引擎正在逐步淘汰的原因。这就是为什么MongoDB必须使用集群来扩展的原因。

    如果您拥有较小的数据集大小和较少的并发性,它可以工作,因此它可能足以在一个使用不当的网站上创建登录。新登录可能不会经常创建,因此需要进行大规模扩展。

    但是,用户登录,密码更改或帐户属性的其他更改确实会更频繁地发生。

    解决方法是使此操作成为原子,以避免竞争条件。例如,尝试插入并使数据库引擎验证唯一性,如果违反该约束,则拒绝插入。

    不幸的是,我没有在tiedot中看到任何文档,表明它支持索引的唯一约束或唯一性强制执行。

    Tiedot 98%由一位开发人员撰写,期限约为2年(2013年5月 - 2015年4月)。此后活动非常少(见https://www.openhub.net/p/tiedot)。我认为tiedot是一个实验项目,不太可能扩展功能集。

相关问题