Redis란 무엇인가?

Redis란?
오픈 소스 기반의 고성능 키-값 저장소 시스템으로, 메모리 내 데이터 구조 저장을 지원하는 NoSQL 데이터베이스이다.

데이터베이스는 데이터를 물리 디스크에 작성한다.
(장점) 서버가 다운되더라도 물리 디스크에 데이터가 남아있다.
(단점) 사용자가 늘어날 경우, 데이터베이스에 부하가 생겨 느려진다.

Redis는 캐시 서버로서,
데이터를 메모리에 저장하여 같은 요청이 온다면 메모리에 있는 데이터를 읽어 빠르게 응답할 수 있다.
즉, 매번 물리 디스크에 접근하지 않기 때문에 데이터베이스의 부하를 줄일 수 있다.

db-engines에서 key value 유형 중 1위이다.

Redis의 주요 특징

메모리 기반 데이터 저장

Redis는 데이터를 메모리에 저장하므로 빠른 읽기 및 쓰기가 가능하다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisExampleService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void writeToRedis() {
        // 데이터 쓰기
        redisTemplate.opsForValue().set("example_key", "Hello, Redis!");
    }

    public String readFromRedis() {
        // 데이터 읽기
        return redisTemplate.opsForValue().get("example_key");
    }
}

지속성

Redis는 디스크에 데이터를 저장하는 옵션도 제공하여, 데이터의 지속성을 보장할 수 있다. 이를 통해 시스템 재시작, 서버 다운 시에도 데이터 손실을 방지할 수 있다.

다양한 데이터 구조 지원

Redis는 문자열, 해시, 리스트, 집합, 정렬 집합 등 다양한 데이터 구조를 지원한다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
public class RedisDataStructuresService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void demonstrateDataStructures() {
        // 문자열 저장
        redisTemplate.opsForValue().set("string_key", "Hello, Redis!");

        // 해시 저장
        redisTemplate.opsForHash().put("hash_key", "field1", "value1");

        // 리스트 저장
        redisTemplate.opsForList().rightPush("list_key", "item1");
        redisTemplate.opsForList().rightPush("list_key", "item2");

        // 집합 저장
        redisTemplate.opsForSet().add("set_key", "member1");
        redisTemplate.opsForSet().add("set_key", "member2");

        // 정렬 집합 저장
        redisTemplate.opsForZSet().add("zset_key", "member1", 1.0);
        redisTemplate.opsForZSet().add("zset_key", "member2", 2.0);

        // 데이터 읽기
        String stringValue = redisTemplate.opsForValue().get("string_key");
        System.out.println("String Value: " + stringValue);

        Object hashValue = redisTemplate.opsForHash().get("hash_key", "field1");
        System.out.println("Hash Value: " + hashValue);

        String listItem = redisTemplate.opsForList().index("list_key", 0);
        System.out.println("List Item: " + listItem);

        Set<String> setMembers = redisTemplate.opsForSet().members("set_key");
        System.out.println("Set Members: " + setMembers);

        Set<Object> zsetMembers = redisTemplate.opsForZSet().range("zset_key", 0, -1);
        System.out.println("ZSet Members: " + zsetMembers);
    }
}

Pub/Sub 메시징 패턴

Redis는 Publish/Subscribe 메시징 패턴을 지원하여 메시지 브로커로 사용될 수 있다. 이를 통해 여러 컴포넌트 간의 통신을 구현할 수 있다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.api.ChannelTopicFactoryBean;
import org.springframework.stereotype.Service;

@Service
public class RedisPubSubService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ChannelTopicFactoryBean channelTopicFactoryBean;

    public void publishMessage(String message) {
        // 메시지 발행
        redisTemplate.convertAndSend(getTopic().getTopic(), message);
    }

    public void subscribeToChannel() {
        // 채널 구독
        redisTemplate.getConnectionFactory().getConnection().subscribe((message, bytes) -> {
            String receivedMessage = new String(message.getBody());
            System.out.println("Received message: " + receivedMessage);
        }, getTopic().getTopicBytes());
    }

    private ChannelTopic getTopic() {
        return channelTopicFactoryBean.getObject();
    }
}

트랜잭션

Redis는 여러 명령을 하나의 트랜잭션으로 그룹화하여 실행할 수 있다. 이를 통해 일련의 연관된 작업을 원자적으로 수행할 수 있다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class RedisTransactionService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void performTransaction() {
        // 트랜잭션 실행
        List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
            @Override
            public List<Object> execute(org.springframework.data.redis.connection.RedisConnection connection) {
                // 트랜잭션 시작
                connection.multi();

                // 트랜잭션 내 명령들 실행
                redisTemplate.opsForValue().increment("transaction_key", 1);
                redisTemplate.opsForValue().set("another_key", "Transaction Data");

                // 트랜잭션 종료
                return connection.exec();
            }
        });

        // 트랜잭션 결과 확인
        System.out.println("Transaction Results: " + results);
    }
}

이 코드에서는 SessionCallback을 사용하여 트랜잭션을 정의하고 실행하고 있다. 트랜잭션 내에서 여러 명령을 실행한 후 exec()를 호출하여 트랜잭션을 종료한다.

클라이언트 라이브러리

다양한 프로그래밍 언어에 대한 클라이언트 라이브러리가 제공되어 있어, 다양한 플랫폼 및 언어에서 Redis를 사용할 수 있습니다.

import redis.clients.jedis.Jedis;

public class JedisExample {

    public static void main(String[] args) {
        // Redis 서버에 연결
        try (Jedis jedis = new Jedis("localhost", 6379)) {
            // 데이터 쓰기
            jedis.set("jedis_key", "Hello, Jedis!");

            // 데이터 읽기
            String value = jedis.get("jedis_key");
            System.out.println("Value from Jedis: " + value);
        }
    }
}

이 코드는 Java에서 Jedis 라이브러리를 사용하여 Redis에 연결하고 데이터를 읽고 쓰는 간단한 예시이다.

Redis 사용 시 주의사항

데이터 저장

Redis는 메모리 기반 데이터 저장 시스템이며, 디스크에 데이터를 지속적으로 저장하는 옵션도 제공하기는 한다. 그러나, 무조건 영구적으로 데이터를 저장해야하는 경우에는 백업을 하거나, RDB 백업 파일을 이용하여 데이터를 복구할 수 있도록 조치를 취해야 한다.

메모리 사용량

Redis는 메모리 기반 데이터 저장 시스템이다. 즉, 메모리를 초과하여 데이터를 저장하면 시스템이 불안정해질 수 있다. 메모리 사용량을 모니터링하고 필요에 따라 Redis 설정을 조정하여 메모리 사용을 최적화 해야 한다.
또한, Redis는 싱글쓰레드로 명령어를 처리하기 때문에 한 번에 하나의 명령어를 처리한다. 따라서 cpu, memory를 많이 사용하는 명령어와 구조를 지양해야한다.

보안

Redis는 기본적으로 인증을 사용하지 않는다. Redis를 사용할 때에는 반드시 엑세스 제어를 설정하고, 비밀번호를 설정하여 보안을 강화해야 한다.

profile
나는 아직 멍청하다

0개의 댓글

Powered by GraphCDN, the GraphQL CDN