Lewis Zou
Lewis Zou

Reputation: 41

is there asynchronous issue in redis

If redis is a single thread server, why the result is not 100000? I think it's not redis's issue, but i want to know the reason. Thanks.

        RedisConnection.Default.Database.StringSet("mykey1", 0);
        Parallel.For(0, 50000, new ParallelOptions { MaxDegreeOfParallelism = 2 }, (i) =>
        {
            var number = RedisConnection.Default.Database.StringGet("mykey1");
            int result = int.Parse(number);
            RedisConnection.Default.Database.StringSet("mykey1", result + 1);

        });
        Console.WriteLine("Result" + RedisConnection.Default.Database.StringGet("mykey1"));

Upvotes: 4

Views: 188

Answers (2)

Tague Griffith
Tague Griffith

Reputation: 4183

Because you make two separate calls to Redis, without the use of a transactional block (MULTI/EXEC) your StringGet and StringSet operations are not atomic. Execution of the threads can interleave Get and Set operations.

Think about one possible execution sequence:

  1. Thread1 Reads myKey1=40
  2. Thread2 Reads myKey1=40
  3. Thread2 Writes myKey with 41
  4. Thread2 Reads myKey1 = 41
  5. Thread2 Writes myKey with 42
  6. Thread1 Writes myKey1 with 41

The proper way to write this code is to to replace the separate call to StringGet and StringSet with a call to StringIncrement:

    RedisConnection.Default.Database.StringSet("mykey1", 0);
    Parallel.For(0, 50000, new ParallelOptions { MaxDegreeOfParallelism = 2 }, (i) =>
    {
        RedisConnection.Default.Database. StringIncrement("mykey1");
    });
    Console.WriteLine("Result" + RedisConnection.Default.Database.StringGet("mykey1"));

Upvotes: 0

GuangshengZuo
GuangshengZuo

Reputation: 4687

You could use the MULTI/EXEC to avoid this problem. It will make sure that two command will not be split by other command. It will be a transaction.

Upvotes: 1

Related Questions