Skip to content

Commit

Permalink
DOC: Add examples for the KV API
Browse files Browse the repository at this point in the history
  • Loading branch information
ing-eoking committed Nov 5, 2024
1 parent 2998b0c commit 62b72ea
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 29 deletions.
10 changes: 7 additions & 3 deletions docs/01-arcus-cloud-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ARCUS cache server의 key-value 모델은 아래의 기본 제약 사항을 가

## 서비스코드

서비스코드(service code)는 ARCUS에서 cache cloud를 구분하는 코드이다.
서비스코드(service code)는 ARCUS에서 cache cloud를 구분하는 코드이다.
ARCUS cache cloud 서비스를 응용들에게 제공한다는 의미에서 "서비스코드"라는 용어를 사용하게 되었다.

하나의 응용에서 하나 이상의 ARCUS cache cloud를 구축하여 사용할 수 있다.
Expand All @@ -39,7 +39,7 @@ ARCUS admin은 ZooKeeper를 이용하여 각 서비스 코드에 해당하는 AR
특정 서비스 코드에 대한 cache server list를 관리하며,
cache server 추가 및 삭제에 대해 cache server list를 최신 상태로 유지하며,
서비스 코드에 대한 cache server list 정보를 ARCUS client에게 전달한다.
ARCUS admin은 highly available하여야 하므로,
ARCUS admin은 highly available하여야 하므로,
여러 ZooKeeper 서버들을 하나의 ZeeKeeper ensemble로 구성하여 사용한다.

## Cache Key
Expand Down Expand Up @@ -76,7 +76,7 @@ ARCUS cache는 simple key-value item 외에 다양한 collection item 유형을
## Expiration, Eviction, and Sticky Item

각 cache item은 expiration time 속성을 가진다.
이 값의 설정으로 자동 expiration을 지정하거나 expire되지 않도록 지정할 수 있다.
0을 초과한 값으로 설정하면 자동 expiration이 지정되며, 0으로 설정하면 expire되지 않도록 지정할 수 있다.

ARCUS cache는 memory cache이며, 한정된 메모리 공간을 사용하여 데이터를 caching한다.
메모리 공간이 모두 사용된 상태에서 새로운 cache item 저장 요청이 들어오면,
Expand All @@ -89,3 +89,7 @@ available 메모리 공간을 확보한 후에 새로운 cache item을 저장한
Sticky item의 삭제는 전적으로 응용에 의해 관리되어야 함을 주의해야 한다.
그리고, sticky item 역시 메모리에 저장되기 때문에 server가 restart되면 사라지게 된다.

## Flags

각 cache item은 value와 함께 저장하거나 조회하는 flags 값을 가진다.
이 값은 value의 메타데이터 용도이며, 예시로 value에 저장된 데이터의 유형이나 압축(compression) 여부 등을 나타내기 위해 사용한다.
214 changes: 188 additions & 26 deletions docs/03-key-value-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ Key-value item에 대해 수행 가능한 연산들은 아래와 같다.

key-value item을 저장하는 API로 set, add, replace, prepend/append가 있다.

``` c
새로운 아이템을 저장하거나 기존 아이템을 교체하는 API는 다음과 같다.
- memcached_set: 주어진 key에 value를 저장한다.
- memcached_add: 주어진 key가 존재하지 않을 경우에만 value를 저장한다.
- memcached_replace: 주어진 key가 존재하는 경우에만 value를 저장한다.

```c
memcached_return_t
memcached_set(memcached_st *ptr,
const char *key, size_t key_length,
Expand All @@ -35,12 +40,33 @@ memcached_replace(memcached_st *ptr,
time_t expiration, uint32_t flags)
```
- memcached_set: 주어진 key에 value를 저장한다.
- memcached_add: 주어진 key가 존재하지 않을 경우에만 value를 저장한다.
- memcached_replace: 주어진 key가 존재하는 경우에만 value를 저장한다.
대표적으로 set을 수행하는 예시는 다음과 같다.
```c
int arcus_kv_store(memcached_st *memc)
{
const char *key= "item:a_key";
const char *value= "value";
uint32_t exptime= 600;
uint32_t flags= 0;
memcached_return_t rc;
rc= memcached_set(memc, key, strlen(key), value, strlen(value), exptime, flags);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_set: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}
assert(rc == MEMCACHED_SUCCESS);
return 0;
}
```

존재하는 아이템의 value에 데이터를 추가시키는 API는 다음과 같다.
- memcached_prepend: 주어진 key의 value에 새로운 데이터를 prepend한다.
- memcached_append: 주어진 key의 value에 새로운 데이터를 append한다.

``` c
```c
memcached_return_t
memcached_prepend(memcached_st *ptr,
const char *key, size_t key_length,
Expand All @@ -53,20 +79,35 @@ memcached_append(memcached_st *ptr,
time_t expiration, uint32_t flags)
```
- memcached_prepend: 주어진 key의 value에 새로운 데이터를 prepend한다.
- memcached_append: 주어진 key의 value에 새로운 데이터를 append한다.
대표적으로 prepend를 수행하는 예시는 다음과 같다.
Key-value item 저장 연산에서 주요 파라미터는 아래와 같다.
- expiration: key가 현재 시간부터 expire 될 때까지의 시간(초 단위). 시간이 30일을 초과하는 경우 expire 될 unix time을 입력한다.
- 0: key가 expire 되지 않도록 설정한다.
하지만 ARCUS cache server의 메모리가 부족한 경우 LRU에 의해 언제든지 삭제될 수 있다.
- -1: key를 sticky item으로 만든다. Sticky item은 expire 되지 않으며 LRU에 의해 삭제되지도 않는다.
- flags: value와는 별도로 저장할 수 있는 값으로서 Java client 등에서 내부적으로 사용하는 경우가 많으므로 사용하지 않기를 권한다.
```c
int arcus_kv_attach(memcached_st *memc)
{
const char *key= "item:a_key";
const char *value= "value";
uint32_t exptime= 600;
uint32_t flags= 0;
memcached_return_t rc;
rc= memcached_prepend(memc, key, strlen(key), value, strlen(value), exptime, flags);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_prepend: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}
assert(rc == MEMCACHED_SUCCESS);
return 0;
}
```

## Key-Value Item 조회

Key-value item을 조회하는 API는 두 가지가 있다.

하나의 키에 대한 값을 조회하는 API는 아래와 같다.
반환된 결과가 NULL이 아닌 경우 반드시 free 해주어야 한다.

```c
char *
memcached_get(memcached_st *ptr,
Expand All @@ -75,7 +116,39 @@ memcached_get(memcached_st *ptr,
memcached_return_t *error)
```
주어진 key에 대한 value를 조회한다. 반환된 결과는 NULL이 아닌 경우 반드시 free 해주어야 한다.
하나의 키의 값을 조회하는 예시는 다음과 같다.
```c
int arcus_kv_get(memcached_st *memc)
{
const char *key= "item:a_key";
const char *value;
size_t value_length;
uint32_t flags;
memcached_return_t rc;
value= memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_get: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}
assert(rc == MEMCACHED_SUCCESS);
if (value != NULL) {
fprintf(stdout, "memcached_get: %s=%s\n", key, value);
free((void*)value);
} else {
fprintf(stdout, "memcached_get: %s=<empty value>.\n", key);
}
return 0;
}
```

여러 키들의 값들을 일괄 조회하는 API는 다음과 같다.
- `memcached_mget`은 주어진 key 배열에 대한 value들을 조회하는 요청을 보낸다.
- keys 인자는 key pointer array이고, key_length 인자는 key length array이다.
- `memcached_fetch`는 mget 요청에 대한 결과를 하나씩 가져온다.
- error 값이 MEMCACHED_END가 될 때까지 계속 실행하면 되며, 반환된 결과가 NULL이 아닌 경우 반드시 free 해주어야 한다.

```c
memcached_return_t
Expand All @@ -89,18 +162,64 @@ memcached_fetch(memcached_st *ptr,
memcached_return_t *error)
```
`memcached_mget`은 주어진 key 배열에 대한 value들을 조회하는 요청을 보낸다.
keys 인자는 key pointer array이고, key_length 인자는 key length array이다.
여러 키들의 값을 일괄 조회하는 예시는 다음과 같다.
```c
int arcus_kv_mget(memcached_st *memc)
{
const char * const keys[]= { "item:a_key1", "item:a_key2", "item:a_key3" };
size_t keys_len[3];
size_t number_of_keys = 3;
uint32_t flags;
memcached_return_t rc;
for (size_t i=0; i<number_of_keys; i++)
{
keys_len[i]= strlen(keys[i]);
}
rc= memcached_mget(memc, keys, keys_len, number_of_keys);
if (rc == MEMCACHED_FAILURE) {
fprintf(stderr, "Failed to memcached_get: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}
`memcached_fetch`는 mget 요청에 대한 결과를 하나씩 꺼내온다.
error 값이 MEMCACHED_END가 될 때까지 실행하면 되며, 그 이후에 fetch를 수행하면 MEMCACHED_NOTFOUND가 반환된다.
assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_SOME_ERRORS);
while (true)
{
char key[MEMCACHED_MAX_KEY];
size_t key_length;
size_t value_length;
char *value= memcached_fetch(memc, key, &key_length, &value_length, &flags, &rc);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_fetch: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}
if (rc == MEMCACHED_END) {
break;
}
assert(rc == MEMCACHED_SUCCESS);
if (value != NULL) {
fprintf(stdout, "memcached_mget: %s=%s\n", key, value);
free((void*)value);
} else {
fprintf(stdout, "memcached_mget: %s=<empty value>.\n", key);
}
}
return 0;
}
```

## Key-Value Item 값의 증감

Key-value item에서 숫자형 value 값에 대해서만 아래 증감 연산을 수행할 수 있다.
특정 key에 해당하는 item이 가진 숫자형 값을 증감 연산하는 API는 다음과 같다.
- offset 만큼 증가/감소하며, 증감 후의 값을 value 인자로 반환한다.
- 해당 item이 없거나 해당 item이 숫자형 값을 가지지 않는다면 오류를 낸다.

``` c
```c
memcached_return_t
memcached_increment(memcached_st *ptr,
const char *key, size_t key_length,
Expand All @@ -111,8 +230,11 @@ memcached_decrement(memcached_st *ptr,
uint32_t offset, uint64_t *value)
```
주어진 key의 value를 offset 만큼 증가/감소 시킨다.
주어진 key가 존재하지 않으면, 오류를 낸다.
특정 key에 해당하는 item이 있다면 증감 연산을 수행하고,
그 item이 없다면 초기값을 가진 item을 생성하는 API는 다음과 같다.
- 해당 item이 있다면 offset 만큼 증가/감소한다.
- 해당 item이 없다면 initial 값을 가진 item을 생성한다.
- 증감 or 생성 후의 item의 값을 value 인자로 반환한다.
```c
memcached_return_t
Expand All @@ -127,19 +249,59 @@ memcached_decrement_with_initial(memcached_st *ptr,
uint64_t *value)
```

주어진 key의 value를 offset 만큼 증가/감소 시킨다.
주어진 key가 존재하지 않으면, initial 값으로 저장한다.
특정 item의 숫자형 값을 증가시키는 예시는 다음과 같다.

```c
int arcus_kv_arithmetic(memcached_st *memc)
{
const char *key= "item:a_key";
uint64_t value= 0;
// uint64_t initial = 0;
uint32_t flags= 10;
uint32_t exptime= 600;
uint32_t offset= 10;
memcached_return_t rc;

rc= memcached_increment(memc, key, strlen(key), offset, &value);
// rc= memcached_increment_with_initial(memc, key, strlen(key), offset, initial, flags, exptime, &value);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_increment: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}

assert(rc == MEMCACHED_SUCCESS);
fprintf(stdout, "incremented value: %llu\n", value);
return 0;
}
```
## Key-Value Item 삭제
주어진 key에 해당하는 item을 삭제하는 API는 다음과 같다.
expiration은 현재 지원하지 않으며, 0을 값으로 주어야 한다.
```c
memcached_return_t
memcached_delete(memcached_st *ptr,
const char *key, size_t key_length,
time_t expiration)
```

주어진 key를 삭제한다.
expiration은 현재 지원하지 않으며, 0을 값으로 주어야 한다.
특정 key를 가진 item을 제거하는 예시는 다음과 같다.

```c
int arcus_kv_delete(memcached_st *memc)
{
const char *key= "item:a_key";
memcached_return_t rc;

rc= memcached_delete(memc, key, strlen(key), 0);
if (memcached_failed(rc)) {
fprintf(stderr, "Failed to memcached_delete: %d(%s)\n", rc, memcached_strerror(memc, rc));
return -1;
}

assert(rc == MEMCACHED_SUCCESS);
return 0;
}
```

0 comments on commit 62b72ea

Please sign in to comment.