广州 网站建设网络推广网页设计网站推广有哪些举措
- 作者: 五速梦信息网
- 时间: 2026年04月20日 11:04
当前位置: 首页 > news >正文
广州 网站建设网络推广网页设计,网站推广有哪些举措,抖音小程序游戏怎么免广告拿奖励,网站建设公司华网天下买送活动前言 在 Web 应用开发过程中#xff0c;防抖#xff08;Debounce#xff09; 是确保同一操作在短时间内不会被重复触发的一种有效手段。常见的场景包括防止用户在短时间内重复提交表单#xff0c;或者避免多次点击按钮导致后台服务执行多次相同的操作。无论在单机环境中防抖Debounce 是确保同一操作在短时间内不会被重复触发的一种有效手段。常见的场景包括防止用户在短时间内重复提交表单或者避免多次点击按钮导致后台服务执行多次相同的操作。无论在单机环境中还是在分布式系统中都有一些场景需要使用它。本文将介绍如何在ASP.NET Core中通过使用锁的方式来实现防抖从而保证无论在单个或多实例部署的情况下都能有效避免重复操作。 分布式锁接口定义 要实现分布式锁的第一步是定义一个通用的锁接口。通过 IDistributedLock 接口应用程序可以在不同的场景中选择使用不同类型的锁来实现。 public interface IDistributedLock {/// summary/// 尝试获取分布式锁。/// /summary/// param nameresourceKey要锁定的资源标识。/param/// param namelockDuration锁的持续时间。/param/// returns是否成功获取锁。/returnsTaskbool TryAcquireLockAsync(string resourceKey, TimeSpan? lockDuration null);/// summary/// 释放分布式锁。/// /summary/// param nameresourceKey要释放的资源标识。/paramTask ReleaseLockAsync(string resourceKey); }这个接口定义了两个核心方法 TryAcquireLockAsync尝试获取分布式锁。如果锁获取成功则返回 true否则返回 false。ReleaseLockAsync释放已获取的锁允许其他操作进入临界区。 Redis 版本的分布式锁实现 在日常开发的方案中Redis 是一个常见的分布式锁实现方式。通过 Redis 的原子操作配合SETNX指令可以确保在多个实例环境中只有一个实例能够获取到锁。下面是 Redis 版本的分布式锁实现代码。 public class RedisDistributedLock : IDistributedLock {private readonly ConnectionMultiplexer _redisConnection;private IDatabase _database;public RedisDistributedLock(ConnectionMultiplexer redisConnection){_redisConnection redisConnection;_database _redisConnection.GetDatabase();}public Taskbool TryAcquireLockAsync(string resourceKey, TimeSpan? lockDuration null){var isLockAcquired _database.StringSetAsync(resourceKey, 1, lockDuration, When.NotExists);return isLockAcquired;}public Task ReleaseLockAsync(string resourceKey){return _database.KeyDeleteAsync(resourceKey);} }在这个实现中使用的是StackExchange.Redis的SDK当然大家可以自行选择合适的库来实现主要是演示起来方便因为其他库需要用脚本自行实现可过期的SETNX 我们使用了 ConnectionMultiplexer 来管理与 Redis 的连接。TryAcquireLockAsync 方法使用了 StringSetAsync 方法其中 When.NotExists 参数确保只有在键不存在时才能成功设置值从而实现锁的功能。ReleaseLockAsync 方法简单地删除了锁对应的键从而释放锁。 如果你选用其它Redis的SDK一般需要写脚本来实现可以过期的SETNX可以参考下面的LUA脚本 – 参数: KEYS[1] 表示键ARGV[1] 表示值ARGV[2] 表示过期时间秒 if redis.call(SETNX, KEYS[1], ARGV[1]) 1 thenredis.call(EXPIRE, KEYS[1], ARGV[2])return 1 elsereturn 0 end使用 SETNX 尝试设置键 KEYS[1] 的值为 ARGV[1]。如果键不存在则返回 1 并成功设置键如果键已存在则返回 0。如果 SETNX 返回 1则为该键设置过期时间过期时间为 ARGV[2] 秒。最终脚本返回 1 表示成功设置了键值对并设置了过期时间返回 0 表示键已经存在操作未成功。 本地锁的实现 在某些情况下例如单机或单体应用中使用本地锁可能会更为合适。这个时候使用基于内存的本地锁实现效果可能会更好。有的同学可能会担心请求量的问题导致内存占用过高的问题。其实换个角度考虑如果有很大请求量或并发量大多数我们可能不会直接使用单机。好了我们继续来看这里我们为了方便直接使用ConcurrentDictionary来实现。 public class LocalLock : IDistributedLock {private readonly ConcurrentDictionarystring, byte lockCounts new ConcurrentDictionarystring, byte();public Taskbool TryAcquireLockAsync(string resourceKey, TimeSpan? lockDuration null){byte lockCount 0;if (lockCounts.TryAdd(resourceKey, lockCount)){lockCounts[resourceKey] 1;return Task.FromResult(true);}return Task.FromResult(false);}public Task ReleaseLockAsync(string resourceKey){lockCounts.TryRemove(resourceKey, out _);return Task.CompletedTask;} }在这个实现中 我们使用 ConcurrentDictionary 来管理锁的状态确保线程安全。TryAcquireLockAsync 方法尝试在字典中添加一个键如果成功则表示获取锁成功。ReleaseLockAsync 方法从字典中移除对应的键从而释放锁。 其实如果C#提供ConcurrentHashSet的话用ConcurrentHashSet来实现会更好一点。毕竟ConcurrentDictionary是KV的方式来是实现每个Value都会浪费一定的内存空间。当然你也可以选择自行实现一套ConcurrentHashSet需要注意的是实现的时候尽量使用桶锁避免使用全局锁。 防抖过滤器的实现 接下来我们使用上面定义的IDistributedLock和Filter来实现防抖过滤器我们创建一个基于 IAsyncActionFilter 接口实现的过滤器更方便我们在请求执行前后获取和释放锁操作。 public class DistributedLockFilterAttribute : Attribute, IAsyncActionFilter {private readonly string _lockPrefix;private readonly LockType _lockType;public DistributedLockFilterAttribute(string keyPrefix, LockType lockType LockType.Local){_lockPrefix keyPrefix;_lockType lockType;}public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){IDistributedLock distributedLock context.HttpContext.RequestServices.GetRequiredKeyedServiceIDistributedLock(_lockType.GetDescription());string controllerName context.RouteData.Values[controller]?.ToString() ?? ;string actionName context.RouteData.Values[action]?.ToString() ?? ;//用户信息或其他唯一标识都可var userKey context.HttpContext.User!.Identity!.Name;string lockKey ${lockPrefix}:{userKey}:{controllerName}{actionName};bool isLockAcquired await distributedLock.TryAcquireLockAsync(lockKey);if (!isLockAcquired){context.Result new ObjectResult(new { code 400, message 请不要重复操作 });return;}try{await next();}finally{await distributedLock.ReleaseLockAsync(lockKey);}} }在这个过滤器的操作中 我们通过容器和LockType获取具体的分布式锁实现。使用 controllerName 和 actionName 以及用户标识构(或其他唯一标识)建锁的键确保锁的唯一性。如果获取锁失败则直接返回错误响应避免后续操作的执行。在操作执行完毕后无论是否成功都释放锁。 为了更灵活地在不同的锁实现之间进行切换我们定义了一个枚举 LockType通过扩展方法 GetDescription 获取其描述方便我们使用它的值。 public enum LockType {[Description(redis)]Redis,[Description(local)]Local }public static class EnumExtensions {public static string GetDescription(this Enum enum){Type type enum.GetType();string name Enum.GetName(type, enum);if (name null){return null;}FieldInfo field type.GetField(name);DescriptionAttribute attribute System.Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;if (attribute null){return name;}return attribute?.Description;} }这个扩展方法可以更方便地根据枚举的类型获取对应的枚举描述从而在依赖注入中灵活的选择不同锁的实现如果有更好的实现方式也可以我们尽量使用更容易懂的方式。 注册和使用过滤器 在ASP.NET Core中我们可以通过依赖注入的方式注册分布式锁相关的服务并在控制器操作中应用防抖过滤器的功能以下是注册和使用分布式锁的示例代码。 builder.Services.AddSingletonConnectionMultiplexer(_ ConnectionMultiplexer.Connect(builder.Configuration[Redis:ConnectionString]!)); //给IDistributedLock添加不同的实现 builder.Services.AddKeyedSingletonIDistributedLock, RedisDistributedLock(LockType.Redis.GetDescription()); builder.Services.AddKeyedSingletonIDistributedLock, LocalLock(LockType.Local.GetDescription());在这里我们注册了 Redis 和本地两种分布式锁实现并使用键key区分它们以便在运行时根据需要选择具体的锁类型。 接下来在控制器的操作方法上应用我们定义的 DistributedLockFilter 过滤器用来实现Action的防抖功能。 [HttpGet(GetCurrentTime)] [DistributedLockFilter(GetCurrentTime, LockType.Redis)] public async Taskstring GetCurrentTime() {await Task.Delay(10000); // 模拟长时间操作return DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); }在这个简单的示例中 DistributedLockFilter 过滤器确保了当用户请求 GetCurrentTime 操作时不会在短时间内重复触发相同的操作。锁的类型被设置为 LockType.Redis因此在分布式环境下多个实例之间也可以共享这个锁当然这个类型是可选的。 如果是在10s之内连续多次请求则会返回如下错误 {code: 400,message: 请不要重复操作 }总结 本文详细介绍了如何在 ASP.NET Core 中使用分布式锁实现防抖功能。通过定义通用的 IDistributedLock 接口我们可以实现不同类型的锁机制包括 Redis 和本地内存锁。Redis 锁利用其原子操作确保分布式环境中的唯一性而本地锁则适用于单机环境。通过创建 DistributedLockFilter 过滤器我们将锁机制集成到 ASP.NET Core 控制器中防止对Action进行重复操作。 这种方法不仅提高了应用的稳定性也增强了用户体验避免了短时间内重复操作的问题。希望本文对大家有所帮助。如果有任何问题或进一步讨论的需求欢迎在评论区留言。
- 上一篇: 广州 网站的设计公司wordpress新文章无法
- 下一篇: 广州h5网站开发html表白简单代码
相关文章
-
广州 网站的设计公司wordpress新文章无法
广州 网站的设计公司wordpress新文章无法
- 技术栈
- 2026年04月20日
-
广州 互联网公司 网站首页上海公布最新情况
广州 互联网公司 网站首页上海公布最新情况
- 技术栈
- 2026年04月20日
-
广州 海珠 建网站游戏开发制作培训
广州 海珠 建网站游戏开发制作培训
- 技术栈
- 2026年04月20日
-
广州h5网站开发html表白简单代码
广州h5网站开发html表白简单代码
- 技术栈
- 2026年04月20日
-
广州icp网站测评经典软文广告
广州icp网站测评经典软文广告
- 技术栈
- 2026年04月20日
-
广州icp网站测评外贸物流流程
广州icp网站测评外贸物流流程
- 技术栈
- 2026年04月20日
