原子地只增加id

时间:2017-01-31 18:04:59

标签: c# mongodb

以下函数的目的是创建存储数字序列和usedId的IdentityStore对象。一旦我们达到行的最大尺寸,它将删除集合并从0开始重新创建它。我需要此操作以原子方式工作,因为数字序列必须是唯一的。目前它不起作用。我可以采取什么方法来锁定每个呼叫的此功能。

可以有多个服务器,并且将运行多个实例。这只会锁定单个实例并且多个服务器之间存在竞争条件。如何在多个实例/机器上锁定它。

  

编辑:

我现在明白,我需要使用Mutex,以便线程能够跨应用程序的多个实例使用此代码块。如果Mutex不存在,请使用现有的互斥锁。这个实现是否正确?我使用了多线程单元测试,目前正在通过。但我不确定代码块是否会在互斥锁中正确执行。在阅读了关于此主题的MSDM文件后,我基于此实现

https://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx

private int _sequence = 0;
private long _lastgen = -1;
private MongoDBRepository<IdentityStore> _mongoDBRepository;


public MongoIdGenerator(string mongoConnectionString)
{
_mongoDBRepository = new MongoDBRepository<IdentityStore>(mongoConnectionString);
}

public string GetIdForKey(string key, int maxSize)
{
var requestInitialOwnership = true;
bool mutexWasCreated;
Mutex m = new Mutex(
        requestInitialOwnership,
        "MyMutex", 
        out mutexWasCreated);

// This thread owns the mutex only if it both requested  
// initial ownership and created the named mutex. Otherwise, 
// it can request the named mutex by calling WaitOne. 
if (!(requestInitialOwnership && mutexWasCreated))
{
    m.WaitOne();
}

// Once the process has gained control of the named mutex, 
// Hold onto it until the mongo record has been successfully created.
var collection = _mongoDBRepository.Collection;
IdentityStore idStore = new IdentityStore();
idStore.key = string.Empty;

if (_lastgen != -1)
{
    idStore = collection.AsQueryable().OrderByDescending(i => i.usedId).FirstOrDefault();

    if (_sequence < maxSize && idStore != null)
    {
        var arrayOfDigits = _sequence.ToString().Select(digit => int.Parse(digit.ToString()));
        var _sequenceOfNumbers = _sequence.ToString().PadLeft((10 - arrayOfDigits.Count()), '0');

        idStore.key = _sequenceOfNumbers;
        idStore.usedId = _sequence;

        _sequence++;
    }
    else
    {
        collection.Database.DropCollection(collection.CollectionNamespace.CollectionName);

        _sequence = 0;
        _lastgen = 0;

        idStore.key = "000000000";
        idStore.usedId = _sequence;

        _sequence++;
    }
}
else
{
    _sequence = 0;
    _lastgen = 0;

    idStore.key = "000000000";
    idStore.usedId = _sequence;

    _sequence++;
}

unchecked
{
    collection.InsertOne(idStore);

    // Call ReleaseMutex to allow other threads to gain control 
    // of the named mutex. If you keep a reference to the local 
    // Mutex, you can call WaitOne to request control of the  
    // named mutex.
    m.ReleaseMutex();
    return idStore.key;

}

0 个答案:

没有答案
相关问题