Redis Bitmap 실습: 비트 단위 데이터 처리

2024. 9. 11. 10:49·DB/Redis

Redis에서 발생한 오류는 SETBIT 명령어에 전달된 비트 값이 유효하지 않기 때문입니다. SETBIT 명령어는 특정 비트 위치에 0 또는 1만 설정할 수 있습니다. 다른 값(예: 3, 11, 01 등)은 유효한 비트 값이 아니므로, Redis는 ERR bit is not an integer or out of range 오류를 반환합니다.

세부 분석:

  1. 정상적으로 비트 설정 (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이었음을 의미합니다.
  1. 비트 값 조회
    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
  • 설정한 비트 값들을 정상적으로 조회할 수 있습니다.
  1. 비트 값 재설정
    SETBIT request-somepage-20230105 130 1  # 다시 130번째 비트를 1로 설정
    (integer) 1  # 이전 비트 값은 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 실습: 키-필드-값 데이터 구조 관리하기  (2) 2024.09.11
'DB/Redis' 카테고리의 다른 글
  • Redis Key와 Scan 명령어: 대규모 데이터 검색
  • Redis 트랜잭션: 안전한 데이터 변경 처리하기
  • Redis Geospatial 실습: 좌표 기반 데이터 처리
  • Redis Sorted Set 실습: 정렬된 데이터를 효율적으로 처리하기
hyeseong-dev
hyeseong-dev
안녕하세요. 백엔드 개발자 이혜성입니다.
  • hyeseong-dev
    어제 오늘 그리고 내일
    hyeseong-dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (286) N
      • 여러가지 (107)
        • 알고리즘 & 자료구조 (72)
        • 오류 (4)
        • 이것저것 (29)
        • 일기 (1)
      • 프레임워크 (39)
        • 자바 스프링 (39)
        • React Native (0)
      • 프로그래밍 언어 (38)
        • 파이썬 (30)
        • 자바 (3)
        • 스프링부트 (5)
      • 컴퓨터 구조와 운영체제 (3) N
      • DB (17)
        • SQL (0)
        • Redis (17)
      • 클라우드 컴퓨팅 (2)
        • 도커 (2)
        • AWS (0)
      • 스케쥴 (65)
        • 세미나 (0)
        • 수료 (0)
        • 스터디 (24)
        • 시험 (41)
      • 트러블슈팅 (1)
      • 자격증 (0)
        • 정보처리기사 (0)
      • 재태크 (5)
        • 암호화폐 (5)
        • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    DP
    WebFlux
    자바
    Redis
    완전탐색
    파이썬
    시험
    AWS
    Docker-compose
    #개발자포트폴리오 #개발자이력서 #개발자취업 #개발자취준 #코딩테스트 #항해99 #취리코 #취업리부트코스
    docker
    ecs
    Spring Boot
    celery
    FastAPI
    RDS
    mybatis
    그리디
    Python
    EC2
    spring
    프로그래머스
    SAA
    백준
    java
    취업리부트
    Spring WebFlux
    reactor
    OOP
    항해99
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
hyeseong-dev
Redis Bitmap 실습: 비트 단위 데이터 처리
상단으로

티스토리툴바