Синхронизация выполняемых задач на NLB-кластере (вопрос)

Одним прекрасным днём появилась как-то задача - обеспечить синхронизацию обрабатываемых записей. Требовалось исключить повторную обработку, которая, к тому же, занимала значительное время.

Решение нашлось очень быстро - создание именованного мьютекса:

using System.Threading;
using System.Security.Principal;
using System.Security.AccessControl;

...

public SomeResponseType HandleRecord(string recordId)
{
	SomeResponseType result = null;
	bool hasHandle = false;

	// создаём Mutex с кодом запис вместо имени
	Mutex m = CreateMutex(recordId);
	hasHandle = m.WaitOne(100, false);
	
	if (!hasHandle)
	{
		// Определили, что кто-то уже обрабатывает запись с этим кодом
		// возвращаем второму клиенту сообщение 'Данная запись уже в обработке'
		return ...
	}

	try
	{
		// это единственный вызов - обрабатываем запись
		...
	}
	catch (Exception ex)
	{
		...
	}
	finally
	{
		if (hasHandle)
		{
			m.ReleaseMutex(); 
		}
	}

	return result;
}

/// <summary>
/// Создаём глобальный именованный Mutex 
/// + раздаём права на него другим пользователям.
/// </summary>
/// <param name="recordId">GUID записи, который станет именем мьютекса</param>
/// <returns></returns>
private static Mutex CreateMutex(string recordId)
{
	var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

	// MutexSecurity позволяет задать права на создаваемый объект
	// мьютекса, чтобы другие пользователи могли иметь к нему доступ
	var mutexsecurity = new MutexSecurity();
	
	mutexsecurity.AddAccessRule(
		new MutexAccessRule(
			sid,
			MutexRights.FullControl,
			AccessControlType.Allow));

	mutexsecurity.AddAccessRule(
		new MutexAccessRule(
			sid,
			MutexRights.ChangePermissions,
			AccessControlType.Deny));

	mutexsecurity.AddAccessRule(
		new MutexAccessRule(
			sid,
			MutexRights.Delete,
			AccessControlType.Deny));

	bool created;

	// создаём Mutex с идентификатором обрабатываемой записи вместо имени
	return new Mutex(false, "Global\\" + recordId, out created, mutexsecurity);
}

Всё прекрасно работало, пока не было перенесено с одиночного сервера на NLB-кластер.

Почему сломалось? Понятно, что при распределении клиентских запросов на разные сервера найти мьютекс на другой машине не представляется возможным, каким бы глобальным он не был.

Хочется выслушать теперь мнение матёрых читателей: какое решение можно использовать на NLB для данной задачи?

Русский
field_vote: 
1.96154
Average: 2 (26 votes)

Добавить комментарий