Redis 트래픽 미러링 구현

배경

Redis 시나리오에서 비용을 절감하고 효율성을 높이려면 일부 Redis 인스턴스를 Community Pika와 같은 Redis 프로토콜을 지원하는 SSD 디스크 스토리지 프로젝트(Alibaba Cloud Tair)로 마이그레이션하여 스토리지 비용을 줄이는 것이 필요합니다. 마이그레이션 프로세스에는 성능 검증이 필요하며, 비즈니스 마이그레이션 성능 및 명령어 호환성 안정성을 보장하기 위해 기본 선택 및 스트레스 테스트 외에도 비즈니스 시나리오별로 전체 명령어 성능 범위를 수행해야 합니다. 기존 접근 방식은 작은 지역에서 이중 트래픽 또는 그레이 스케일 트래픽을 수행하는 프로젝트에 비즈니스 개발의 협력을 요구하는 것입니다.

위의 문제와 상관없이 더 많은 인력과 시간을 투자해야 하므로 비용 절감과 효율성 향상 자체 측면에서 ROI가 크게 감소합니다. 원본 Redis의 모든 읽기 트래픽을 대상 Redis SSD 인스턴스로 직접 재생할 수 있다면 전체 이벤트 SRE 마이그레이션을 99% 완료할 수 있으며 인스턴스 마이그레이션 시간도 대폭 단축되므로 Redis 트래픽 미러링의 필요성이 생겨났습니다.

팁: 당사의 데이터 마이그레이션 솔루션은 Alibaba Cloud의 DTS를 사용합니다. DTS는 Redis 마스터-슬레이브 복제 원칙을 기반으로 구현되므로 데이터 동기화 프로세스 중에 쓰기 트래픽 성능을 직접 확인할 수 있습니다.

연구

Google과 Github에서 찾아봤지만 별로 적합한 것이 없어서 결국 직접 조사하기로 결정했습니다. 발견된 일부 관련 정보는 다음과 같습니다.

  • Alibaba Cloud의 SLS Redis 감사 로그

Alibaba Cloud의 Redis 인스턴스는 Redis 실행 로그를 SLS(로그 기록 및 쿼리 제품)로 전송하여 기록하는 것을 지원하지만 쓰기 트래픽만 기록하므로 Redis 읽기 트래픽 재생 요구 사항을 충족하지 않습니다.

이 도구는 pika 프로젝트에서 폐기되었습니다. 현재는 문서만 있고 창고에는 관련 코드가 없습니다. 그러나 이 글의 구현 역시 pika와 동일한 구현 원칙을 기반으로 합니다.

istio 기반의 Redis 미러링 트래픽은 반드시 istio에 연결되어야 하는데 한계가 너무 크고 새로운 istio 구성 요소를 도입하려면 많은 안정성 테스트가 필요하므로 이 경로는 바로 거부됩니다.

성취하다

이 요구 사항을 충족하려면 주제로 직접 이동하여 Redis의 모니터 명령을 사용하세요.

/**
 * @author kl (http://kailing.pub)
 * @since 2023/9/27
 */
public class RedisMonitorTest {

    static final JedisPool targetRedisPool = new JedisPool("127.0.0.1", 6398);
    static final JedisPool sourceRedisPool = new JedisPool("127.0.0.1", 6379);
    static final Set<String> redisReadCommands = new HashSet<>(Arrays.asList(
            "get", "strlen", "exists", "getbit", "getrange", "substr", "mget", "llen", "lindex",
            "lrange", "sismember", "scard", "srandmember", "sinter", "sunion", "sdiff", "smembers",
            "sscan", "zrange", "zrangebyscore", "zrevrangebyscore", "zrangebylex", "zrevrangebylex",
            "zcount", "zlexcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "zscan", "hget",
            "hmget", "hlen", "hstrlen", "hkeys", "hvals", "hgetall", "hexists", "hscan", "randomkey",
            "keys", "scan", "dbsize", "type", "sync", "psync", "ttl", "touch", "pttl", "dump", "object",
            "memory", "bitcount", "bitpos", "georadius_ro", "georadiusbymember_ro", "geohash",
            "geopos", "geodist", "pfcount", "xrange", "xrevrange", "xlen", "xread", "xpending",
            "xinfo", "lolwut"
    ));
    
    public static void main(String[] args) {
            try (Jedis jedis = sourceRedisPool.getResource()) {
                jedis.monitor(new JedisMonitor() {
                    @Override
                    public void onCommand(String command) {
                        sendCommand(command);
                    }
                });
            }
    }
    
    public static void sendCommand(String commandStr) {
        String[] parts = commandStr.split("\"");
        if (parts.length < 2) {
            return;
        }
        String cmd = parts[1];
        List<String> args = new ArrayList<>();
        for (int i = 3; i < parts.length; i += 2) {
            args.add(parts[i]);
        }
        if (redisReadCommands.contains(cmd.toLowerCase())) {
            ProtocolCommand command = () -> cmd.getBytes(StandardCharsets.UTF_8);

            try (Jedis jedis = targetRedisPool.getResource()) {
                try {
                    long startTime = System.currentTimeMillis();
                    jedis.sendCommand(command, args.toArray(new String[0]));
                    System.out.println(cmd + ":" + (System.currentTimeMillis() - startTime));
                } catch (Exception e) {
                    System.err.println(cmd + e.getMessage());
                }
            }
        }
    }
}

위는 실행을 위해 sourceRedis에서 targetRedis로 모든 읽기 트래픽을 전달하기 위해 직접 실행할 수 있는 의사 코드 조각입니다.

구문 분석 구현

위에서 사용한 Java Redis 클라이언트 jedis를 개발하는데, 먼저 monitor 명령어를 호출하는데, 이 명령어는 차단 명령어로 Redis 서버의 명령어 실행 기록을 항상 구독하게 되며, 기록 형식은 다음과 같다.

1695869359.747056 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869359805247076" "LIMIT" "0" "1"
1695869359.748040 [0 127.0.0.1:64257] "EXISTS" "asynq:{sys}:paused"
1695869359.748259 [0 127.0.0.1:64257] "EXISTS" "asynq:{sync}:paused"
1695869359.748578 [0 127.0.0.1:64257] "EXISTS" "asynq:{default}:paused"
1695869359.748916 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869359869190783" "LIMIT" "0" "1"
1695869359.749154 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869359877625076" "LIMIT" "0" "1"
1695869359.749348 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869359878760313" "LIMIT" "0" "1"
1695869359.749530 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869359882064571" "LIMIT" "0" "1"
1695869359.779048 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869360024586886" "LIMIT" "0" "1"
1695869359.785898 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869360031603858" "LIMIT" "0" "1"
1695869359.786092 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869360031656719" "LIMIT" "0" "1"
1695869359.786923 [0 127.0.0.1:64257] "ZRANGEBYSCORE" "delayed_tasks" "0" "1695869360031666910" "LIMIT" "0" "1"

따라서 지침을 구문 분석하여 대상 인스턴스로 보내면 됩니다.

여기에는 읽기 지침만 사용하여 레코드를 필터링하는 방법에 대한 질문도 있습니다.

chatGPT에 물어보려고 했는데 전혀 신뢰가 안가더라구요.. 읽기 명령어가 빠졌거나, 다른 쓰기 명령어를 사용해서 숫자를 만들어낸 건지.. 그래서 믿을 수 없습니다. 다행스럽게도 Redis 서버는 읽기 명령과 쓰기 명령을 구별하기 위해 각 명령을 표시합니다.

따라서 모든 읽기 전용 지침을 콘솔에 인쇄하고 복사하여 이 문제를 해결하세요.

지침

Redis monitor 명령은 Redis의 성능을 손상시키는 명령으로, 공식 테스트에서는 Redis 단일 인스턴스의 성능이 약 50% 정도 감소하게 되는데, 실제 테스트에서는 Redis의 실제 부하가 높지 않을 때 이러한 영향은 다음과 같다. 무시할 수 있습니다(특히 QPS가 높은 경우). 예시를 주의해서 사용하세요. Redis 독립형 QPS는 10W를 지원할 수 있기 때문입니다. 예를 들어 온라인 실시간 QPS 1W의 경우 모니터를 사용할 때 QPS와 RT는 거의 변화가 없습니다.

또한, 모니터를 장시간 실행하면 Redis의 메모리 소모가 증가하므로 성능 검증을 할 경우에는 항상 실행하지 않고 시간을 조절하는 것이 가장 좋습니다.

결론

이 블로그에서는 Redis 트래픽 미러링의 구현 방법과 비용 절감 및 효율성 향상에 있어서의 중요성에 대해 논의합니다. 기존 검증 방식은 Redis 인스턴스 마이그레이션 시 많은 인력과 시간 투자가 필요해 비용 절감 및 효율성 향상에 따른 ROI가 감소한다는 사실을 알게 되었습니다. 이 문제를 해결하기 위해 Redis 트래픽 미러링 요구 사항이 도입되었습니다.

원본 Redis의 모든 읽기 트래픽을 대상 Redis SSD 인스턴스에 직접 재생함으로써 인스턴스 마이그레이션 프로세스를 효율적으로 완료하고 SRE의 작업 부하를 줄이며 마이그레이션 시간을 크게 단축할 수 있습니다. 이 방법은 마이그레이션 프로세스의 효율성을 향상시킬 뿐만 아니라 비용과 위험을 줄여 비용 절감 및 효율성 향상 목표를 보다 실현 가능하고 달성 가능하게 만듭니다. 이 접근 방식을 채택함으로써 Redis 인스턴스를 보다 효율적으로 마이그레이션하고 비즈니스 성능과 안정성을 유지하는 동시에 비용을 절감하고 효율성을 높일 수 있습니다.

읽어 주셔서 감사합니다! 질문이나 아이디어가 있으시면 언제든지 댓글을 남겨주세요.

오픈 소스 프레임워크 NanUI의 작성자가 철강 판매로 전환하여 프로젝트가 중단되었습니다. Apple App Store의 무료 목록 1위는 포르노 소프트웨어인 TypeScript입니다. 이제 막 인기를 얻었는데 왜 대기업들은 이를 포기하기 시작합니까? ? TIOBE 10월 목록: Java가 가장 큰 감소세를 보이고 C#은 Java Rust 1.73.0 출시 에 가까워지고 있습니다. 한 남자가 AI 여자친구의 부추김을 받아 영국 여왕을 암살했으며 9년 징역형을 선고받았습니다. Qt 6.6 공식 출시 Reuters: RISC-V 기술이 중미 기술 전쟁의 핵심이 된다 새로운 전장 RISC-V: 단일 기업이나 국가에 의해 통제되지 않는 Lenovo, Android PC 출시 계획
{{o.이름}}
{{이름}}

Je suppose que tu aimes

Origine my.oschina.net/klblog/blog/10115744
conseillé
Classement