C# --- 使用Redis分布式锁实现初始化任务

背景

  • service A 在启动时需要读取一些配置文件,并根据配置文件的内容对数据库进行更新
  • service A有多个实例,所以在启动时会重复进行初始化,浪费资源

解决方案 — 分布式锁

可以使用分布式锁 + version number的方式实现只让一个实例进行初始化任务

  • version number: .Net应用在编译时(不管代码有没有改变)都会生成一个assembly module version id
  • version number存在数据库里,用于对比

具体步骤:

  • 多个实例同时启动,不断尝试获取分布式锁
  • 实例A拿到锁,使用自身的version number和数据库里的进行对比,如果不一致则说明初始化任务还未进行,则执行初始化任务,完成后释放锁
  • 实例B获取锁,使用自身的version number和数据库里的进行对比,发现version number一致,则说明已执行完初始化任务,跳过初始化任务
//.Net的 Redis library
using RedLockNet 

private async Task<IRedLock> AcquireLock()
{
  //时间分别为:expireTime,waitTime,retryTime
  var dLock= await _lockFactory.CreateLockAsync(LockKey, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(70), TimeSpan.FromSeconds(2),
  if (dLock.IsAcquired)
  {
  	return dLock
  }
  await dLock.Dispose();
  throw Exception("Cannot get lock within wait time")
}
public async DoInitTask()
{
	await using var distributedLock = await AcquireLock()
	var newVersion = GetNewVersion();
	var curVersion = GetVersionFromDB();
	if (newVersion = curVersion) 
	{
		log("already init")
		return 
	}
	
	//do init task
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐