验证 Redis INCR 命令的原子性
想确认一下 INCR 命令是不是原子性的,所以写了段代码试了一下。
安装所需包
额外安装了一个 Args 包用来解析命令行参数,具体文档参考 这里。
powershell
Install-Package StackExchange.Redis -Version 2.0.601
Install-Package Args -Version 1.2.1示例代码
同时对变量 varCount 执行 ++ 操作来跟 Redis 做对比。
csharp
using StackExchange.Redis;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace RedisMultiThreadsIncrement
{
class Program
{
static void Main(string[] args)
{
var parameter = Args.Configuration.Configure<Parameter>().CreateAndBind(args);
var sw = Stopwatch.StartNew();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
string counterKey = "counter";
int varCount = 0;
db.StringSet(counterKey, 0);
Task[] tasks = new Task[parameter.TaskCount];
for (int i = 0; i < parameter.TaskCount; i++)
{
tasks[i] = Task.Run(() =>
{
for (int j = 0; j < parameter.PerTaskCount; j++)
{
db.StringIncrement(counterKey);
varCount++;
}
});
}
Task.WaitAll(tasks);
Console.WriteLine($"Last counter result: {db.StringGet(counterKey)}");
Console.WriteLine($"Last varCount: {varCount}");
sw.Stop();
Console.WriteLine($"Increment {parameter.TaskCount} * {parameter.PerTaskCount} 次(耗时:{sw.ElapsedMilliseconds} ms)");
Console.WriteLine("press <enter> to exit.");
Console.ReadLine();
}
}
/// <summary>
/// 参数模型
/// </summary>
class Parameter {
/// <summary>
/// 线程数
/// </summary>
public int TaskCount { get; set; } = 10;
/// <summary>
/// 每个线程的计数次数
/// </summary>
public int PerTaskCount { get; set; } = 100;
}
}执行结果
执行了数次,Redis 最后的结果都是相同的,而变量 varCount 的值则几乎每次都不相同,而且没有一次是正确的结果。
powershell
>dotnet run /TaskCount 100 /PerTaskCount 1000
Last counter result: 100000
Last varCount: 99962
Increment 100 * 1000 次(耗时:5251 ms)
press <enter> to exit.总结
很明显可以看出 INCR 是原子性的自增操作。
参考官方文档 INCR key,其中确实提到了 INCR 是 原子的增加操作。
The counter pattern is the most obvious thing you can do with Redis atomic increment operations. The idea is simply send an
INCRcommand to Redis every time an operation occurs.