website/content/docs/dev/concepts/explore-tikv-features/cas.md

104 lines
3.2 KiB
Markdown

---
title: CAS on RawKV
description: Compare And Swap
menu:
"dev":
parent: Features-dev
weight: 4
identifier: CAS on RawKV-dev
---
This page walks you through a simple demonstration of performing compare-and-swap (CAS) in TiKV.
In RawKV, compare-and-swap (CAS) is an atomic instruction to achieve synchronization between multiple threads.
Performing CAS is an atomic equivalent of executing the following code:
```
prevValue = get(key);
if (prevValue == request.prevValue) {
put(key, request.value);
}
return prevValue;
```
The atomicity guarantees that the new value is calculated based on the up-to-date information. If the value is updated by another thread at the same time, the write would fail.
## Prerequisites
Make sure that you have installed TiUP, jshell, downloaded tikv-client JAR files, and started a TiKV cluster according to [TiKV in 5 Minutes](../../tikv-in-5-minutes).
## Verify CAS
To verify whether CAS works, you can take the following steps.
### Step 1: Write the code to test CAS
Save the following script to the `test_raw_cas.java` file.
```java
import java.util.Optional;
import org.tikv.common.TiConfiguration;
import org.tikv.common.TiSession;
import org.tikv.raw.RawKVClient;
import org.tikv.shade.com.google.protobuf.ByteString;
TiConfiguration conf = TiConfiguration.createRawDefault("127.0.0.1:2379");
// enable AtomicForCAS when using RawKVClient.compareAndSet or RawKVClient.putIfAbsent
conf.setEnableAtomicForCAS(true);
TiSession session = TiSession.create(conf);
RawKVClient client = session.createRawClient();
ByteString key = ByteString.copyFromUtf8("Hello");
ByteString value = ByteString.copyFromUtf8("CAS");
ByteString newValue = ByteString.copyFromUtf8("NewValue");
// put
client.put(key, value);
System.out.println("put key=" + key.toStringUtf8() + " value=" + value.toStringUtf8());
// get
Optional<ByteString> result = client.get(key);
assert(result.isPresent());
assert("CAS".equals(result.get().toStringUtf8()));
System.out.println("get key=" + key.toStringUtf8() + " result=" + result.get().toStringUtf8());
// cas
client.compareAndSet(key, Optional.of(value), newValue);
System.out.println("cas key=" + key.toStringUtf8() + " value=" + value.toStringUtf8() + " newValue=" + newValue.toStringUtf8());
// get
result = client.get(key);
assert(result.isPresent());
assert("NewValue".equals(result.get().toStringUtf8()));
System.out.println("get key=" + key.toStringUtf8() + " result=" + result.get().toStringUtf8());
// close
client.close();
session.close();
```
### Step 2: Run the code
```bash
jshell --class-path tikv-client-java.jar:slf4j-api.jar --startup test_raw_cas.java
```
The example output is as follows:
```bash
put key=Hello value=CAS
get key=Hello result=CAS
cas key=Hello value=CAS newValue=NewValue
get key=Hello result=NewValue
```
As in the example output, after calling `compareAndSet`, the value `CAS` is replaced by `newValue`.
{{< warning >}}
- To ensure the linearizability of `CAS` when it is used together with `put`, `delete`, `batch_put`, or `batch_delete`, you must set `conf.setEnableAtomicForCAS(true)`.
- To guarantee the atomicity of CAS, write operations such as `put` or `delete` in atomic mode take more resources.
{{< /warning >}}