Command like redis incr :atomic increment operations

I want to give the user a non-repetition of id

I do not want to use uuid,

I want to use auto-incremented long value

Here is some example code that

  • increments a counter
  • decrements a counter
  • increments a counter and returns the new value
Key coounterKey = new Key(this.namespace, this.set, "my-counter");
/*
 * increment the counter by 1
 */
Bin counterBin = new Bin("some-counter", 1);
this.client.add(null, coounterKey, counterBin);
/*
 * increment the counter by 15
 */
counterBin = new Bin("some-counter", 15);
this.client.add(null, coounterKey, counterBin);
/*
* increment the counter by 1 and return the new value
*/
counterBin = new Bin("some-counter", 1);
Record record = this.client.operate(null, coounterKey, Operation.add(counterBin), Operation.get("some-counter"));
System.out.println("New value: " + record.getLong("some-counter"));
/*
 * decrement the counter by 5
 */
counterBin = new Bin("some-counter", -5);
this.client.add(null, coounterKey, counterBin);

I hope this helps

Thank you for your answer,

But I think in multiple threads,increments a counter and returns the new value,This result will be problems

It will not, because the increment operation is atomic. If you are using multi-ops you can tell it to both increment and read the value, so there is no time between those operations for something else to happen. You will perform both operations together. So you can increment a counter and get its value at that time, post-increment.

Does increment operation in Aerospike updates TTL of record?

Yes, increment will update a record’s TTL.

1 Like

Hello!

Can you show this code for php? A saw operation like “operate” and I want to know, if this is the same like INCR in Redis?

$key = $client->initKey("test", "users", 1234);
$operations = [
 ["op" => Aerospike::OPERATOR_INCR, "bin" => "age", "val" => 1],
 ["op" => Aerospike::OPERATOR_READ, "bin" => "age"],
];
$options = [Aerospike::OPT_TTL => 600];
$status = $client->operate($key, $operations, $returned, $options);
if ($status == Aerospike::OK) {
    var_dump($returned);
} else {
    echo "[{$client->errorno()}] ".$client->error();
}

Is the same like INCR in Redis? So is it atomic?

The code in your snippet looks correct for an increment of a bin, and a read of the new value.

The operate method in the PHP Client will cause all of the provided operations to be applied atomically. The value of the "age" bin will be incremented, and its new value will be returned to the client.

1 Like

Thanks!

So one more question - is in Aerospike function like bRPopLPush (in Redis)? I need to move element from List1 to List2. So it should be atomic. I mean there are 600 operations that will do the same, but I need that only one operation can do it and then return element back, and so on. Its like queue. Is this implementation in php language for this operation?

Aerospike does not currently have an equivalent atomic operation for either RPOPLPUSH or BRPOPLPUSH.

1 Like

So, is there any other ways to do it?

Presently, there isn’t an ‘operation’ to do such. You can write a UDF in LUA to do this atomically. UDF is currently the only solution for atomic multi-bin inter-bin operations.

Even if I will make pop operation? When I make pop operation - so it must be atomic operation. In manual there is: Atomic list operations only work against top level elements, not nested values (https://www.aerospike.com/docs/guide/cdt-list.html) So will it be atomic? And can I use it for queue?

That is saying that an operation such as list_pop is able to remove an element from the list, but not able to remove an element from a sublist.

For example

list = [1, 2, 3, [4, 5, 6]]
remove_by_index(list, -1) ## List = [1,2,3] now

But if list is:

list = [1, 2, 3, [4, 5, 6]]

With our current operations, you can not do something like remove a single element from the list stored in the last position of the main list. So, with our current operations, you cannot change list to:

[1, 2, 3, [4, 5]]

Using UDFs you can do these types of operations, and operate on multiple bins in the same record atomically.

Unless if -2 is passed in the policy, right?

That’s now correct - a lot can change in 4 years :laughing:.

What to we need to do for multiple counter with some value ?

You can, in the same operation, increment multiple bins with different increments by chaining the different operations… I am not a client developer so maybe this is a very poor way of doing this but it seems to work as one would expect…

    Bin incr1 = new Bin ("bin1", 1);
    Bin incr2 = new Bin ("bin2", 3);

    Bin bin1 = new Bin ("bin1", 5);
    Bin bin2 = new Bin ("bin2", 8);
    Key key = new Key("test", "testset", "key1");
    client.put(null, key, bin1, bin2);

    Record record = client.get(null, key);
    client.operate(null, key, Operation.add(incr1), Operation.add(incr2));
    Record record2 = client.get(null, key);
    
    System.out.println("Record before operate: " + record);
    System.out.println("Record after  operate: " + record2);


Record before operate: (gen:1),(exp:355024488),(bins:(bin1:5),(bin2:8))
Record after  operate: (gen:2),(exp:355024488),(bins:(bin1:6),(bin2:11))
1 Like

This topic was automatically closed 84 days after the last reply. New replies are no longer allowed.