Redis는 싱글스레드를 기반으로 작업이 처리된다.
즉, 클라이언트로부터 전달받은 명령어를 순차적으로 수행하는데,
이때 하나의 명령어가 수행시간이 오래걸리면 줄지어있는 다른 명령어가 모두 대기하게 된다. (지연시간 발생)
👉🏻 in-memory database
의 장점이 사라지는 것!
Redis 대부분의 명령어는 O(1)
이지만, O(n)
으로 처리되는 것을 특히 주의해야 한다.
linsert
, hkeys
, hgetall
, smembers
가 O(n)COUNT
값 만큼씩 데이터를 가져옴SCAN 0
에서 반환된 커서를 사용해 다음 SCAN
을 호출하면, 전체 데이터를 순차적으로 가져올 수 있음MATCH
(필터링)로 특정 패턴의 key만 검색가능KEYS
의 대안으로 SCAN
을 사용import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
public class RedisScanExample {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("127.0.0.1", 6379)) {
String cursor = "0"; // 초기 커서는 0
ScanParams params = new ScanParams().match("user:*").count(10);
do {
ScanResult<String> scanResult = jedis.scan(cursor, params);
cursor = scanResult.getCursor(); // 다음 스캔을 위한 커서 업데이트
scanResult.getResult().forEach(System.out::println);
} while (!cursor.equals("0")); // 커서가 0이면 종료
}
}
}
# Redis Bash 실행
docker exec -it <docker 컨테이너 ID> /bin/bash
# 대량 Key - value 생성
for i in {0000000..9999999}; do echo set key$i $i>> redis-strings.txt; done
# echo -> 출력, key$i $i -> key value 같은 값
# 파일 실행
cat redis-strings.txt
# redis-cli pipeline으로 실행 (대량 배치 작업에 용이)
cat redis-strings.txt | redis-cli --pipe
# KEYS -> O(n)
KEYS *
# SCAN -> O(1)
> scan 0 match * count 100
1) 9633792 (cursor 값)
2) 1) "key3628497"
2) "key6700864"
. . .
> scan 9633792(cursor 값) match * count 100