Redis에서 발생한 오류는 SETBIT
명령어에 전달된 비트 값이 유효하지 않기 때문입니다. SETBIT 명령어는 특정 비트 위치에 0
또는 1
만 설정할 수 있습니다. 다른 값(예: 3
, 11
, 01
등)은 유효한 비트 값이 아니므로, Redis는 ERR bit is not an integer or out of range
오류를 반환합니다.
세부 분석:
- 정상적으로 비트 설정 (100, 120, 130 비트에
1
설정)SETBIT request-somepage-20230105 100 1 # 100번째 비트를 1로 설정 (integer) 0 # 이전 비트 값은 0 SETBIT request-somepage-20230105 120 1 # 120번째 비트를 1로 설정 (integer) 0 # 이전 비트 값은 0 SETBIT request-somepage-20230105 130 1 # 130번째 비트를 1로 설정 (integer) 0 # 이전 비트 값은 0
- 정상적으로 비트가 설정되며, 반환 값
0
은 설정되기 전 비트 값이0
이었음을 의미합니다.
- 비트 값 조회
GETBIT request-somepage-20230105 130 # 130번째 비트를 조회 (integer) 1 # 비트 값은 1 GETBIT request-somepage-20230105 100 # 100번째 비트를 조회 (integer) 1 # 비트 값은 1 GETBIT request-somepage-20230105 120 # 120번째 비트를 조회 (integer) 1 # 비트 값은 1
- 설정한 비트 값들을 정상적으로 조회할 수 있습니다.
- 비트 값 재설정
SETBIT request-somepage-20230105 130 1 # 다시 130번째 비트를 1로 설정 (integer) 1 # 이전 비트 값은 1 (변경 없음)
- 여기서 비트 값을 다시 설정했을 때, 이전 비트 값이
1
이었으므로1
을 반환합니다.
- 비트 값에 유효하지 않은 값 설정 시 오류 발생
SETBIT request-somepage-20230105 130 3 # 3은 유효한 비트 값이 아님 (error) ERR bit is not an integer or out of range SETBIT request-somepage-20230105 130 11 # 11도 유효하지 않은 비트 값 (error) ERR bit is not an integer or out of range SETBIT request-somepage-20230105 130 01 # 01도 잘못된 비트 값 (error) ERR bit is not an integer or out of range
- 비트 값은 항상 0 또는 1이어야 합니다. 그 외의 숫자를 입력하면 Redis는 오류를 반환합니다.
요약:
- SETBIT는 특정 위치에
0
또는1
을 설정하는 명령어입니다. - 비트 값으로
3
,11
,01
등은 허용되지 않으며, 비트 값은 0 또는 1만 가능합니다. - GETBIT는 특정 위치의 비트 값을 조회하는 명령어입니다.
Java Code
package org.example;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
try(var jedisPool = new JedisPool("127.0.0.1", 6379)) {
try(var jedis = jedisPool.getResource()) {
jedis.setbit("request-somepage-20230305", 100, true);
jedis.setbit("request-somepage-20230305", 200, true);
jedis.setbit("request-somepage-20230305", 300, true);
System.out.println(jedis.getbit("request-somepage-20230305", 100));
System.out.println(jedis.getbit("request-somepage-20230305", 50));
System.out.println(jedis.bitcount("request-somepage-20230305"));
// bitmap vs set
Pipeline pipelined = jedis.pipelined();
IntStream.rangeClosed(0, 100000).forEach(i -> {
pipelined.sadd("request-somepage-set-20230306", String.valueOf(i), "1");
pipelined.setbit("request-somepage-bit-20230306", i, true);
if (i == 1000) {
pipelined.sync();
}
});
pipelined.sync();
}
}
}
}
이 코드는 Redis의 비트맵(Bitmap) 및 Set 자료구조를 사용하는 예제로, Redis와 Jedis 라이브러리를 사용하여 비트맵과 집합(Set)의 성능 및 메모리 효율성을 비교하는 목적을 가지고 있습니다. 각각의 부분에 대해 설명드리겠습니다.
1. 비트맵 설정 (SETBIT
) 및 조회 (GETBIT
)
jedis.setbit("request-somepage-20230305", 100, true);
jedis.setbit("request-somepage-20230305", 200, true);
jedis.setbit("request-somepage-20230305", 300, true);
- 설명:
SETBIT
명령어는 특정 위치에 비트 값을1
또는0
으로 설정합니다. 여기서는 100, 200, 300번째 비트에true
(=1)을 설정하고 있습니다. - 목적: Redis의 비트맵을 사용하여 각 위치의 비트를
1
로 설정함으로써, 비트맵을 통해 특정 플래그나 상태를 효율적으로 저장할 수 있습니다.
System.out.println(jedis.getbit("request-somepage-20230305", 100));
System.out.println(jedis.getbit("request-somepage-20230305", 50));
- 설명:
GETBIT
명령어는 특정 위치의 비트 값을 조회합니다. 100번째 비트는1
로 설정되어 있어true
가 출력되고, 50번째 비트는 설정되지 않았기 때문에 기본 값0
이 출력됩니다.
System.out.println(jedis.bitcount("request-somepage-20230305"));
- 설명:
BITCOUNT
명령어는 비트맵 내에서1
로 설정된 비트의 개수를 반환합니다. 여기서는 100, 200, 300번째 비트가1
로 설정되어 있으므로 출력 결과는3
입니다.
2. 비트맵 vs Set 성능 테스트 (Pipeline 사용)
Pipeline pipelined = jedis.pipelined();
IntStream.rangeClosed(0, 100000).forEach(i -> {
pipelined.sadd("request-somepage-set-20230306", String.valueOf(i), "1");
pipelined.setbit("request-somepage-bit-20230306", i, true);
if (i == 1000) {
pipelined.sync();
}
});
pipelined.sync();
설명
- 비트맵:
SETBIT
을 통해 0부터 100,000까지의 비트 위치를1
로 설정합니다. - 집합(Set):
SADD
명령어를 통해0
부터100,000
까지의 값을 집합에 추가합니다. - Pipeline:
Pipeline
을 사용하여 여러 명령어를 한 번에 처리하도록 구현하여 네트워크 요청을 줄이고 성능을 높입니다. 1,000개의 명령어가 처리될 때마다sync()
를 호출하여 명령어를 서버로 전송하고 나머지 명령어를 계속 처리합니다.
목적: 비트맵과 집합(Set)의 성능 및 메모리 사용을 비교하기 위한 예시입니다.
- 비트맵은 메모리를 매우 효율적으로 사용하며, 상태 저장이 간단할 때 유리합니다.
- 집합(Set)은 중복되지 않는 값들의 집합을 저장할 수 있지만, 메모리 사용량은 비트맵에 비해 상대적으로 더 큽니다.
요약:
1. 비트맵:
- 특정 비트 위치에
1
또는0
값을 설정하거나 조회할 수 있습니다. BITCOUNT
명령어로1
로 설정된 비트의 개수를 쉽게 계산할 수 있습니다.- 비트맵은 큰 범위의 데이터를 메모리 효율적으로 처리할 수 있는 자료구조입니다.
2. Set:
SADD
를 통해 값을 집합에 추가할 수 있습니다.- 중복되지 않는 값을 저장할 때 유용하지만, 많은 데이터를 저장할 때 비트맵에 비해 메모리 사용량이 큽니다.
3. Pipeline:
Pipeline
은 여러 Redis 명령어를 한 번에 처리하여 네트워크 요청을 줄이고 성능을 향상시킵니다.- 이 코드에서는 1,000개의 명령어마다
sync()
를 호출하여 명령어를 서버로 전송하고 있습니다.
Memory 효율 Bitmap vs Set
Redis에서 비트맵과 셋(Set) 자료구조를 사용하여 10만 개의 데이터를 처리한 후, 각 자료구조의 메모리 사용량을 비교한 결과가 다음과 같습니다:
1. Set의 메모리 사용량
MEMORY USAGE request-somepage-set-20230306
(integer) 4248776
- 설명:
request-somepage-set-20230306
라는 Set 자료구조의 메모리 사용량을 조회한 결과, 약 4,248,776 바이트(약 4.2MB)가 사용되었습니다. - Set 자료구조는 각 요소가 고유해야 하며, 문자열로 저장되기 때문에 상대적으로 더 많은 메모리를 차지합니다.
2. 비트맵(Bitmap)의 메모리 사용량
MEMORY USAGE request-somepage-bit-20230306
(integer) 16456
- 설명:
request-somepage-bit-20230306
라는 비트맵 자료구조의 메모리 사용량을 조회한 결과, 약 16,456 바이트(약 16KB)가 사용되었습니다. - 비트맵은 비트를 압축하여 저장하기 때문에 메모리 효율이 매우 높습니다. 각 비트는 0 또는 1의 값만을 저장하므로, 메모리 사용량이 최소화됩니다.
분석 및 결론:
- Set 자료구조는 약 4.2MB의 메모리를 사용한 반면, 비트맵(Bitmap)은 16KB만을 사용했습니다.
- 비트맵이 Set보다 훨씬 적은 메모리를 사용하여 효율적으로 데이터를 처리할 수 있음을 알 수 있습니다. 특히, 플래그나 상태를 저장하는 데 비트맵을 사용하면 메모리 효율을 극대화할 수 있습니다.
- Set은 중복되지 않는 값들을 저장하는 데 유리하지만, 많은 수의 데이터를 처리할 때는 비트맵이 훨씬 적은 메모리를 차지하기 때문에 성능 및 효율성 면에서 더 우수합니다.
따라서, 상태나 플래그 관리와 같이 0 또는 1과 같은 단순한 값을 저장해야 할 경우에는 비트맵을 사용하는 것이 적절합니다.
'DB > Redis' 카테고리의 다른 글
Redis Key와 Scan 명령어: 대규모 데이터 검색 (0) | 2024.09.11 |
---|---|
Redis 트랜잭션: 안전한 데이터 변경 처리하기 (0) | 2024.09.11 |
Redis Geospatial 실습: 좌표 기반 데이터 처리 (0) | 2024.09.11 |
Redis Sorted Set 실습: 정렬된 데이터를 효율적으로 처리하기 (0) | 2024.09.11 |
Redis Hash 실습: 키-필드-값 데이터 구조 관리하기 (0) | 2024.09.11 |