3

Redis incr function behaves erratically. When trying to increment any positive integer key that has not been set yet, it results in the following error. However, when first setting it by set then incrementing using incr for the same key, the problem is no longer there. Any reason why it behaves this way? Any workarounds?

127.0.0.1:6379[5]> incr 100
(error) ERR value is not an integer or out of range
127.0.0.1:6379[5]> incr '100'
(error) ERR value is not an integer or out of range
127.0.0.1:6379[5]> incr "100"
(error) ERR value is not an integer or out of range
127.0.0.1:6379[5]> set 100 1
OK
127.0.0.1:6379[5]> incr 100
(integer) 2

This behavior is only true when incrementing non-existing Integer keys:

127.0.0.1:6379> get "ahmedov"
(nil)
127.0.0.1:6379> incr "ahmedov"
(integer) 1
127.0.0.1:6379> incr "ahmedov"
(integer) 2
127.0.0.1:6379> get 12.1
(nil)
127.0.0.1:6379> incr 12.1
(integer) 1
127.0.0.1:6379> get -1
(nil)
127.0.0.1:6379> incr -1
(integer) 1
Ahmadov
  • 1,567
  • 5
  • 31
  • 48

3 Answers3

2

Until you had actually called the SET command, you were trying to increment a key named '100' that did not contain a valid representation of an integer number.

After setting the key called '100' to the string "1", the increment succeeds and returns 2 (1+1) as expected.

Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
  • But when I type: incr "Ahmedov" for example, without calling Set first, I don't get that error. – Ahmadov Oct 25 '18 at 06:26
  • 1
    That's also expected - calling `INCR` on a nonexisting key implicitly initializes its value to 0. IIRC, this is well referenced in the documentation. – Itamar Haber Oct 25 '18 at 21:22
0

If you are using Java and Spring Boot, here is how you can do it:

Declare an attribute of the class StringRedisTemplate, for example:

private final StringRedisTemplate redisTemplate;

You have two options:

  1. Set and increment
String key = "a";
int value = 3;
redisTemplate.boundValueOps(key).set(String.valueOf(value));
Long turn = redisTemplate.boundValueOps(key).increment(); // -> 4
  1. Increment

You can also increment without setting a value first, in this case the first value will be 1:

String otherKey = "b";
Long turn = redisTemplate.boundValueOps(otherKey).increment(); // -> 1

You can find a complete example here

Julian Espinel
  • 2,586
  • 5
  • 26
  • 20
-1

Please use StringRedisTemplate instead of RedisTemplate for increment operation. Since the 'icrement()' method is a String based activity, it is recommended to use StringRedisTemplate. Please find the sample below.

Define StringRedisTemplate

    @Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
    StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
    stringRedisTemplate.setConnectionFactory(connectionFactory);
    // Add some specific configuration here. Key serializers, etc.
    return stringRedisTemplate;
}

Set increment key with initial value

@Autowired
private StringRedisTemplate stringRedisTemplate;

stringRedisTemplate.opsForValue().set("key", "100");

Get increment

Long increment = stringRedisTemplate.opsForValue().increment("key");

Result

increment is :101

This is verified & working, lets code...

Binu S
  • 9