惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
云风的 BLOG
云风的 BLOG
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
Engineering at Meta
Engineering at Meta
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
Recent Announcements
Recent Announcements
罗磊的独立博客
B
Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX

博客园 - 彪悍的代码不需要注释

AI编写的离线压测工具 虚拟机ftp安装 openclaw本地安装 Redhat服务器离线安装FTP 使用python脚本提取SVN近10年提交记录 本地VMware Workstation Pro的rhel-server-7.9-x86_64服务器配置本地源 敏感词过滤 限流 幂等性 Windows本地生成SSL证书,用于本地调试 【转】大文件上传原理及C#实现方案 WPF创建不规则窗体时WebBrowser控件不显示的问题 QrCode .NET之Kill -15 优雅退出 排查java代码慢-arthas工具 针对clickonce发布后的程序,优化处理省略弹出层 赔率 winform发布ClickOnce到Linux服务器 CentOS obs直播RTMP协议推流到Nginx流媒体服务器到VUE使用HLS直播
【转】C# 实现接口幂等性的四种方案
彪悍的代码不需要注释 · 2024-12-08 · via 博客园 - 彪悍的代码不需要注释

在分布式系统中,幂等性是一个重要的概念。它指的是一次和多次请求某一个资源应该具有同样的效果,即多次执行同样的操作,系统的状态不会发生改变。在网络不稳定或存在重试机制的情况下,保证接口的幂等性尤为重要,它可以防止因重复操作导致的数据不一致问题。

本文将介绍在C#中实现接口幂等性的四种方案,并通过示例代码进行详细说明。

方案一:使用唯一ID

为每次请求生成一个唯一ID(如GUID),在处理请求时,先检查这个ID是否已经被处理过。如果是,则直接返回之前的结果;如果不是,则进行处理并保存结果。

 1 C# 实现接口幂等性的四种方案
 2 原创 lyl 后端Q
 3  2024年06月22日 23:27 福建
 4 在分布式系统中,幂等性是一个重要的概念。它指的是一次和多次请求某一个资源应该具有同样的效果,即多次执行同样的操作,系统的状态不会发生改变。在网络不稳定或存在重试机制的情况下,保证接口的幂等性尤为重要,它可以防止因重复操作导致的数据不一致问题。
 5 
 6 本文将介绍在C#中实现接口幂等性的四种方案,并通过示例代码进行详细说明。
 7 
 8 方案一:使用唯一ID
 9 为每次请求生成一个唯一ID(如GUID),在处理请求时,先检查这个ID是否已经被处理过。如果是,则直接返回之前的结果;如果不是,则进行处理并保存结果。
10 
11 public class IdempotentService
12 {
13     private static readonly ConcurrentDictionary<string, string> Cache = new ConcurrentDictionary<string, string>();
14 
15     public string ProcessRequestWithUniqueId(string requestId, string input)
16     {
17         // 检查请求是否已处理
18         if (Cache.TryGetValue(requestId, out string result))
19         {
20             return result; // 返回之前处理的结果
21         }
22 
23         // 模拟处理过程
24         result = "Processed: " + input;
25         // 保存处理结果
26         Cache[requestId] = result;
27         return result;
28     }
29 }
30 
31 // 使用示例
32 var service = new IdempotentService();
33 string requestId = Guid.NewGuid().ToString(); // 生成唯一ID
34 string input = "Hello, World!";
35 string result = service.ProcessRequestWithUniqueId(requestId, input);
36 Console.WriteLine(result); // 输出:Processed: Hello, World!
37 // 再次使用相同的requestId调用,将返回相同的结果
38 string result2 = service.ProcessRequestWithUniqueId(requestId, "Different Input");
39 Console.WriteLine(result2); // 输出:Processed: Hello, World!(与第一次调用相同)

使用唯一ID

方案二:利用数据库的唯一约束

通过在数据库中设置唯一约束(如唯一索引或主键),可以确保重复插入相同数据时被数据库拒绝,从而实现幂等性。

 1 public class DatabaseIdempotentService
 2 {
 3     // 假设有一个方法用于将数据插入数据库
 4     public bool InsertData(string data)
 5     {
 6         try
 7         {
 8             // 模拟数据库插入操作,如果数据已存在,则抛出异常
 9             if (DataExists(data))
10             {
11                 throw new Exception("Data already exists");
12             }
13             // 模拟成功插入数据
14             Console.WriteLine($"Data inserted: {data}");
15             return true;
16         }
17         catch (Exception)
18         {
19             // 插入失败(可能是重复数据)
20             return false;
21         }
22     }
23 
24     // 模拟检查数据是否存在的方法
25     private bool DataExists(string data)
26     {
27         // 实际开发中,这里应该是查询数据库的操作
28         return false// 示例中始终返回false,表示数据不存在
29     }
30 }
31 
32 // 使用示例
33 var dbService = new DatabaseIdempotentService();
34 string data = "Some unique data";
35 bool result = dbService.InsertData(data); // 尝试插入数据,返回true表示成功,false

利用数据库的唯一约束

方案三:分布式锁

在分布式系统中,可以使用分布式锁来确保同一时间只有一个请求能够执行某个操作。这可以通过Redis等工具的分布式锁功能来实现。

 1 public class DistributedLockIdempotentService
 2 {
 3     private static readonly string LockKey = "my_lock_key";
 4     private readonly IRedisClient _redisClient; // 假设使用StackExchange.Redis等库
 5 
 6     public DistributedLockIdempotentService(IRedisClient redisClient)
 7     {
 8         _redisClient = redisClient;
 9     }
10 
11     public string ProcessRequestWithLock(string input)
12     {
13         // 尝试获取分布式锁
14         if (_redisClient.Lock(LockKey, TimeSpan.FromSeconds(30))) // 锁定30秒
15         {
16             try
17             {
18                 // 模拟处理过程,这里应该是实际的业务逻辑
19                 string result = "Processed with lock: " + input;
20                 return result;
21             }
22             finally
23             {
24                 // 释放锁
25                 _redisClient.Unlock(LockKey);
26             }
27         }
28         else
29         {
30             // 获取锁失败,可能已经有其他请求在处理,返回默认结果或错误信息
31             return "Failed to acquire lock";
32         }
33     }

分布式锁

方案四:状态机幂等

在设计业务逻辑时,可以通过状态机的方式来保证幂等性。即,每个操作都对应一个状态,只有当状态满足一定条件时,操作才能被执行。

 1 public class StateMachineIdempotentService
 2 {
 3     private enum ProcessingState
 4     {
 5         NotStarted,
 6         Processing,
 7         Completed
 8     }
 9 
10     private static readonly ConcurrentDictionary<string, ProcessingState> States = new ConcurrentDictionary<string, ProcessingState>();
11 
12     public string ProcessRequestWithStateMachine(string requestId, string input)
13     {
14         // 检查当前状态
15         var currentState = States.GetOrAdd(requestId, ProcessingState.NotStarted);
16         switch (currentState)
17         {
18             case ProcessingState.NotStarted:
19                 // 更新状态为正在处理中
20                 States[requestId] = ProcessingState.Processing;
21                 // 模拟处理过程
22                 string result = "Processed with state machine: " + input;
23                 // 更新状态为已完成
24                 States[requestId] = ProcessingState.Completed;
25                 return result;
26             case ProcessingState.Processing:
27             case ProcessingState.Completed:
28                 // 如果已经在处理中或已完成,则直接返回之前的结果或错误信息
29                 return "Request already processed";
30             default:
31                 throw new InvalidOperationException("Unknown state");
32         }
33     }
34 }

状态机幂等

在这个示例中,我们使用了一个简单的状态机来跟踪每个请求的处理状态。如果请求已经处理过(处于ProcessingCompleted状态),则直接返回之前的结果。否则,开始处理请求并更新状态。

结论

幂等性在分布式系统中是一个重要的概念,它可以确保系统的稳定性和数据的一致性。本文介绍了四种在C#中实现接口幂等性的方案,包括使用唯一ID、利用数据库的唯一约束、分布式锁和状态机。这些方案各有优缺点,适用于不同的场景和需求。在实际开发中,应根据具体情况选择合适的方案来确保接口的幂等性。