Skip to content

Redis

Redis is an open source, BSD licensed, advanced key-value cache and store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets, sorted sets, bitmaps and hyperloglogs.

Categories

서비스 제공자

URL 만드는 방법

redis[s]://[[username][:password]@][host][:port][/db-number]
  • 만약 사용자 명이 없을 경우 default 로 두거나 없애면 된다.
  • db-number 는 기본값은 0 인듯.

Configuration

Commands

  • AUTH {passwd} - 비밀번호 입력.
  • FLUSHALL - 전체 데이터베이스의 전체 키를 제거.
  • FLUSHDB - 현재 선택된 데이터베이스의 전체 키를 제거.
  • PUBSUB CHANNELS - pub/sub 등록된 채널 목록 출력.
  • PUBLISH {channel} {message} - 해당하는 채널에 메시지를 게시한다.
  • KEYS {pattern} - Returns all keys matching pattern.
  • HGETALL {key} - Returns all fields and values of the hash stored at key.
  • HGET {key} {field} - Returns the value associated with field in the hash stored at key.
  • HSET {key} {field} {value} - Sets the specified fields to their respective values in the hash stored at key.

Redis Lock

Redis vs Memcached

Redis와 MemCached는 모두 인 메모리, 오픈 소스 데이터 스토어입니다. 고성능 분산 메모리 캐시 서비스인 Memcached는 단순성을 위해 설계된 반면 Redis는 광범위한 사용 사례에 효과적이고 풍부한 기능을 제공합니다. 결정을 내리는 데 도움이 되는 보다 자세한 기능 비교를 확인하려면 보려면 Redis 대 Memcached를 참조하십시오. 이들은 MySQL, Postgres, Aurora, Oracle, SQL Server, DynamoDB 등과 같이 성능을 향상시키기 위한 관계형 또는 키-값 데이터베이스를 이용합니다.

Redis vs Postgresql

UID 만 획득하는 방법으로

  • (당연하게도) Redis는 Key 로 획득.
  • (당연하게도) Postgresql은 Select UID Query 로 획득.

결과:

# [Redis] Localhost 10000 iteration average is 0.0006s (WIN, x5 faster)
# [PgSQL] Localhost 10000 iteration average is 0.0031s

Redis 가 약 5배 빠르다.

Redis benchmark

Redis에는 redis-benchmark 라는, 총 M개의 쿼리를 보내는 동시에 N개의 클라이언트가 수행한 명령 실행을 시뮬레이션하는 유틸리티가 포함되어 있습니다.

유틸리티는 기본 테스트 세트를 제공하거나 사용자 정의 테스트 세트를 제공할 수 있습니다.

Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]

Redis 성능에 영향을 미치는 요소

  • 서버와 클라이언트 벤치마크 프로그램이 동일한 상자에서 실행되면 TCP/IP 루프백과 Unix 도메인 소켓을 모두 사용할 수 있습니다. 플랫폼에 따라 Unix 도메인 소켓은 TCP/IP 루프백(예: Linux)보다 약 50% 더 많은 처리량을 달성할 수 있습니다. redis-benchmark의 기본 동작은 TCP/IP 루프백을 사용하는 것입니다.
  • TCP/IP 루프백과 비교하여 Unix 도메인 소켓의 성능 이점은 파이프라인이 많이 사용될 때(예: 긴 파이프라인) 감소하는 경향이 있습니다.
  • 이더넷 네트워크를 사용하여 Redis에 액세스하는 경우 파이프라이닝을 사용하여 명령을 집계하는 것은 데이터 크기가 이더넷 패킷 크기 (약 1500바이트) 미만으로 유지될 때 특히 효율적입니다. 실제로 10바이트, 100바이트 또는 1000바이트 쿼리를 처리하면 처리량이 거의 동일해집니다.
  • 다중 CPU 소켓 서버에서 Redis 성능은 NUMA 구성 및 프로세스 위치에 따라 달라집니다. 가장 눈에 띄는 효과는 클라이언트와 서버 프로세스가 코어에 무작위로 분산되기 때문에 redis-benchmark 결과가 비결정적으로 보인다는 것입니다. 결정적인 결과를 얻으려면 프로세스 배치 도구(Linux: taskset 또는 numactl)를 사용해야 합니다. 가장 효율적인 조합은 항상 클라이언트와 서버를 동일한 CPU의 서로 다른 두 코어에 배치하여 L3 캐시의 이점을 활용하는 것입니다.
  • 고급 구성에서는 클라이언트 연결 수도 중요한 요소입니다. epoll/kqueue를 기반으로 하는 Redis 이벤트 루프는 확장성이 뛰어납니다. Redis는 이미 60000개 이상의 연결로 벤치마킹되었으며 이러한 조건에서도 여전히 50000q/s를 유지할 수 있었습니다. 경험상 30,000개의 연결이 있는 인스턴스는 100개의 연결로 달성할 수 있는 처리량의 절반만 처리할 수 있습니다.
  • 고급 구성에서는 NIC 구성 및 관련 중단을 조정하여 더 높은 처리량을 달성할 수 있습니다. Rx/Tx NIC 대기열과 CPU 코어 간의 선호도를 설정하고 RPS(Receive Packet Steering) 지원을 활성화하면 최고의 처리량을 얻을 수 있습니다. 자세한 내용은 이 스레드를 참조하세요. 점보 프레임은 큰 개체를 사용할 때 성능 향상을 제공할 수도 있습니다.
  • 플랫폼에 따라 Redis는 원시 속도, 내부 및 외부 조각화 측면에서 서로 다른 동작을 가질 수 있는 다양한 메모리 할당자(libc malloc, jemalloc, tcmalloc)에 대해 컴파일될 수 있습니다. Redis를 직접 컴파일하지 않은 경우 INFO 명령을 사용하여 mem_allocator 필드를 확인할 수 있습니다. 대부분의 벤치마크는 상당한 외부 조각화를 생성할 만큼 오래 실행되지 않습니다 (프로덕션 Redis 인스턴스와 달리).

데이터 구조

제한적인 데이터 구조를 제공하는 단순한 키 값 데이터 스토어와 달리 Redis에서는 애플리케이션 요구 사항을 충족할 수 있도록 다양한 데이터 구조를 지원합니다. Redis 데이터 유형은 다음과 같습니다.

  • 문자열 – 최대 512MB 크기의 텍스트 또는 바이너리 데이터
  • 목록 – 추가된 순서가 유지되는 문자열 모음
  • 세트 – 순서가 유지되지 않는 문자열 모음으로 다른 세트 유형과 교차, 통합 및 비교 가능
  • 정렬된 세트 – 값을 기준으로 순서가 지정된 세트
  • 해시 – 필드 및 값의 목록을 저장하는 데이터 구조
  • 비트맵 – 비트 수준 작업을 제공하는 데이터 유형
  • HyperLogLogs – 데이터 세트 내 고유 항목을 추정하기 위한 확률적 데이터 구조

데이터 크기 제한

결론만 말하면 Redis 의 아이템의 크기 제한은 512MB입니다.

서버 메모리 한계 관련

Redis를 사용하여 서비스를 운영하다보면 Redis 서버의 메모리가 한계에 도달할 수 있습니다. 메모리의 한계는 maxmemory 값으로 설정할 수 있습니다. maxmemory 수치까지 메모리가 다 차는 경우 Redis는max memory policy에 따라서 추가 메모리를 확보합니다.

maxmemory-policy 설정값:

  • noeviction : 기존 데이터를 삭제하지 않습니다. 메모리가 꽉 찬 경우에는 OOM(Out Of Memory) 오류 반환하고 새로운 데이터는 버리게 됩니다.
  • allkeys-lru : LRU(Least Recently Used)라는 페이지 교체 알고리즘을 통해 데이터를 삭제하여 공간을 확보합니다.
  • volatile-lru : expire set을 가진 것 중 LRU로 삭제하여 메모리 공간을 확보합니다.
  • allkeys-random : 랜덤으로 데이터를 삭제하여 공간을 확보합니다.
  • volatile-random : expire set을 가진 것 중 랜덤으로 데이터를 삭제하여 공간을 확보합니다.
  • volatile-ttl : expire set을 가진 것 중 TTL(Time To Live) 값이 짧은 것부터 삭제합니다.
  • allkeys-lfu : 가장 적게 액세스한 키를 제거하여 공간을 확보합니다.
  • volatile-lfu : expire set을 가진 것 중 가장 적게 액세스한 키부터 제거하여 공간을 확보합니다.

Maxmemory 초과로 인해서 데이터가 지워지게 되는 것을 eviction이라고 합니다. Redis에 들어가서 INFO 명령어를 친 후 evicted_keys 수치를 보면 eviction이 발생했는지 알 수 있습니다. Amazon Elasticache를 사용하는 경우에는 monitoring tab에 들어가면 eviction에 대한 그래프가 있는데, 이를 통해 Eviction 여부에 대한 알람을 받을 수도 있습니다.

INFORMATION

evicted_keys 값은 evicted된 키들의 count이므로 크면 클수록 많은 데이터가 메모리에서 삭제되었다는 뜻입니다. evicted_keys:0

그런데, Maxmemory가 설정된 대로 작동하면 좋겠지만, 그렇지 않은 경우가 있습니다. Redis는 쓰기 요청이 발생하면 COW(Copy On Write) 방식을 통해 작동합니다. 쓰기 요청이 오면 OS는 fork()를 통해서 자식 프로세스를 생성합니다. fork() 시에는 다른 가상 메모리 주소를 할당받지만 물리 메모리 블록을 공유합니다. 쓰기 작업을 시작하는 순간에는 수정할 메모리 페이지를 복사한 후에 쓰기 작업을 진행합니다. 즉, 기존에 쓰던 메모리보다 추가적인 메모리가 필요합니다. 다만 전체 페이지 중에서 얼마나 작업이 진행될지를 모르기 때문에 fork시에는 기본적으로 복사할 사이즈만큼의 free memory가 필요합니다.

Redis를 직접 설치할 때 /proc/sys/vm/overcommit_memory 값을 1로 설정하지 않아 장애가 날 때가 있습니다. overcommit_memory=0 이면 OS는 주어진 메모리량보다 크게 할당할 수가 없습니다. 즉, fork()시에 OS가 충분한 메모리가 없다고 판단하기 때문에 에러를 발생시킵니다. overcommit_memory=1 로 설정해서 OS한테 일단 over해서 메모리를 할당할 수 있도록 한 후에 max memory에 도달한 경우 policy에 따라 처리되도록 설정하는 것이 좋습니다.

또한 redis에서는 memory 수치 중에서 used_memory_rss 값을 잘 살펴볼 필요가 있습니다. RSS 값은 데이터를 포함해서 실제로 redis가 사용하고 있는 메모리인데, 이 값은 실제로 사용하고 있는 used_memory 값보다 클 수 있습니다. 이러한 현상이 발생하는 이유는 OS가 메모리를 할당할 때 page 사이즈의 배수만큼 할당하기 때문입니다. 예를 들어서 page size = 4096 인데, 요청 메모리 사이즈가 10이라고 하면 OS는 4096만큼을 할당합니다. 이를 Fragmentation(파편화) 현상이라고 하는데, 이것이 실제 사용한 메모리랑 할당된 메모리가 다른 원인이 됩니다.

Redis 보안 설정

/etc/redis.conf에 위치한 Redis 구성 파일 수정:

bind 127.0.0.1
protected-mode yes
port 6379

위의 구성은:

  • Redis가 로컬에서만 접근 가능하도록 설정
  • 보호 모드를 사용하도록 설정하며
  • 기본 포트 6379를 사용하도록 합니다.

비밀번호를 사용한 Redis 인증을 설정하려면, Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다:

requirepass [password]

Redis TLS/SSL 보안을 구성하려면 OpenSSL을 설치하고 SSL 인증서 및 키를 생성해야 합니다. 자세한 내용은 OpenSSL 항목 참조.

Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다.

tls-port 16379
tls-cert-file /path/to/ssl/cert.pem
tls-key-file /path/to/ssl/key.pem

이제 Redis는 TLS/SSL로 암호화된 통신을 사용하여 접근할 수 있습니다.

백업 설정

Redis 데이터를 주기적으로 백업하려면 Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다.

save 900 1
save 300 10
save 60 10000

위의 구성은 Redis 데이터를 15분마다 백업하고, 최소 10개의 변경 사항이 있을 때마다 백업합니다. 또한 1시간마다 10000개의 변경 사항이 있을 때마다 백업합니다. - 확인 요망

Message Queue

Invalidation Message

레디스는 빠르지만, 잦은 데이터 조회는 API 서버에 부담을 줍니다. 특히 실시간 데이터처럼 갱신은 불규칙하지만 자주 조회해야 하는 경우, 효율적인 캐시 전략이 필요합니다.

  • 문제점: Redis PubSub이나 Keyspace Notification은 갱신 감지 및 메시지 처리 로직이 복잡하거나 리소스 낭비를 유발할 수 있습니다.
  • 해결책: Redis 6.0부터 지원하는 Invalidation Message는 서버가 클라이언트 캐시를 관리하는 방식입니다.
    • 클라이언트가 키를 읽은 후 다른 클라이언트가 변경하면, Redis가 갱신 메시지를 보내 캐시를 삭제하도록 합니다.
  • 구현: Go 언어에서 redigo+ristretto 조합 또는 rueidis 라이브러리를 사용하여 Invalidation Message를 적용할 수 있습니다.
    • redigo+ristretto는 커스텀 로직이 필요하지만, rueidis는 DoCache 함수로 간단하게 구현 가능합니다.
  • 결과: 실제 적용 결과, API 응답 속도가 최대 82% 개선되었으며, Redis 서버 부담도 감소했습니다. 클라이언트 사이드 캐시 관리는 필요하지만, 성능 향상 효과가 큽니다.

Docker restart daemon server

docker run -d --restart unless-stopped -e TZ=Asia/Seoul -p 6379:6379 redis:7 redis-server

docker-compose.yml

version: '3.8'

services:
  redis:
    image: redis:6
    restart: always
    volumes:
      - recc_dev_redis_data:/data
    ports:
      - 6379:6379
    environment:
      - TZ=Asia/Seoul
    command: ["redis-server"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  recc_dev_redis_data:

REPLICA

TLS Setting

TLS listening port

TLS만 활성화 하려면 다음과 같이 설정하면 된다.

port 0
tls-port 6379

Running manually

To manually run a Redis server with TLS mode (assuming gen-test-certs.sh was invoked so sample certificates/keys are available):

./src/redis-server --tls-port 6379 --port 0 \
    --tls-cert-file ./tests/tls/redis.crt \
    --tls-key-file ./tests/tls/redis.key \
    --tls-ca-cert-file ./tests/tls/ca.crt

To connect to this Redis server with redis-cli:

./src/redis-cli --tls \
    --cert ./tests/tls/redis.crt \
    --key ./tests/tls/redis.key \
    --cacert ./tests/tls/ca.crt

docker-compose.yml

레디스 7 버전 부터 TLS 가 기본 빌드된듯 하다.

services:
  redis:
    image: 'redis:7.0.11'
    volumes:
      - ./certs/redis-server.crt:/usr/local/etc/redis/redis-server.crt
      - ./certs/redis-server.key:/usr/local/etc/redis/redis-server.key
      - ./certs/ca.crt:/usr/local/etc/redis/ca.crt
    command: >
      redis-server
      --tls-port 6379
      --port 0
      --tls-cert-file /usr/local/etc/redis/redis-server.crt
      --tls-key-file /usr/local/etc/redis/redis-server.key
      --tls-ca-cert-file /usr/local/etc/redis/ca.crt
      --tls-auth-clients no
      --tls-replication yes

utils/gen-redis-certs.sh

레디스 공식 저장소에 있는 사설키 생성 스크립트 utils/gen-redis-certs.sh파일은 다음과 같다:

#!/bin/bash

# Generate some test certificates which are used by the regression test suite:
#
#   tests/tls/ca.{crt,key}          Self signed CA certificate.
#   tests/tls/redis.{crt,key}       A certificate with no key usage/policy restrictions.
#   tests/tls/client.{crt,key}      A certificate restricted for SSL client usage.
#   tests/tls/server.{crt,key}      A certificate restricted for SSL server usage.
#   tests/tls/redis.dh              DH Params file.

generate_cert() {
    local name=$1
    local cn="$2"
    local opts="$3"

    local keyfile=tests/tls/${name}.key
    local certfile=tests/tls/${name}.crt

    [ -f $keyfile ] || openssl genrsa -out $keyfile 2048
    openssl req \
        -new -sha256 \
        -subj "/O=Redis Test/CN=$cn" \
        -key $keyfile | \
        openssl x509 \
            -req -sha256 \
            -CA tests/tls/ca.crt \
            -CAkey tests/tls/ca.key \
            -CAserial tests/tls/ca.txt \
            -CAcreateserial \
            -days 365 \
            $opts \
            -out $certfile
}

mkdir -p tests/tls
[ -f tests/tls/ca.key ] || openssl genrsa -out tests/tls/ca.key 4096
openssl req \
    -x509 -new -nodes -sha256 \
    -key tests/tls/ca.key \
    -days 3650 \
    -subj '/O=Redis Test/CN=Certificate Authority' \
    -out tests/tls/ca.crt

cat > tests/tls/openssl.cnf <<_END_
[ server_cert ]
keyUsage = digitalSignature, keyEncipherment
nsCertType = server

[ client_cert ]
keyUsage = digitalSignature, keyEncipherment
nsCertType = client
_END_

generate_cert server "Server-only" "-extfile tests/tls/openssl.cnf -extensions server_cert"
generate_cert client "Client-only" "-extfile tests/tls/openssl.cnf -extensions client_cert"
generate_cert redis "Generic-cert"

[ -f tests/tls/redis.dh ] || openssl dhparam -out tests/tls/redis.dh 2048

mTLS

mTLS를 위해 서버와 클라이언트 각각에 대한 인증서와 개인 키를 생성해야 합니다. OpenSSL을 사용하여 다음과 같이 인증서와 키를 생성할 수 있습니다:

# 서버용 인증서 및 개인 키 생성
openssl req -x509 -newkey rsa:4096 -keyout server-key.pem -out server-cert.pem -days 365

# 클라이언트용 인증서 및 개인 키 생성
openssl req -x509 -newkey rsa:4096 -keyout client-key.pem -out client-cert.pem -days 365

Redis 구성 파일(redis.conf)을 열고 다음과 같이 TLS 관련 설정을 추가합니다:

tls-port 6379  # TLS 연결을 위한 포트 번호
tls-cert-file /path/to/server-cert.pem  # 서버 인증서 파일 경로
tls-key-file /path/to/server-key.pem    # 서버 개인 키 파일 경로
tls-ca-cert-file /path/to/client-cert.pem  # 클라이언트 인증서 파일 경로
tls-ca-key-file /path/to/client-key.pem    # 클라이언트 개인 키 파일 경로
tls-auth-clients yes  # 클라이언트의 인증을 요구

# 선택적으로 클라이언트 인증을 거부하고 싶다면 아래 설정 추가
# tls-auth-clients no

위 설정에서 /path/to/server-cert.pem 및 /path/to/server-key.pem을 서버의 인증서와 개인 키 파일의 실제 경로로 바꾸고, /path/to/client-cert.pem 및 /path/to/client-key.pem을 클라이언트의 인증서와 개인 키 파일의 실제 경로로 바꿉니다.

redis-py 설치 후 사용:

import redis
import ssl

r = redis.Redis(host='your_redis_server_hostname', port=6379, ssl=True, ssl_certfile='/path/to/client-cert.pem', ssl_keyfile='/path/to/client-key.pem', ssl_cert_reqs=ssl.CERT_OPTIONAL)

ssl_cert_reqs는 인증서 검증 옵션으로 ssl.CERT_OPTIONAL로 설정되어 있으므로 Redis 서버에서 클라이언트 인증이 필수로 요구되지 않을 경우 사용할 수 있습니다. 필수로 요구되는 경우 ssl.CERT_REQUIRED로 설정하십시오.

tls-auth-clients

서버 설정은:

  • tls-auth-clients yes - 클라이언트에 서버의 인증서가 존재해야 한다.
  • tls-auth-clients no - 클라이언트에 서버의 인증서가 없어도 된다.
  • tls-auth-clients optional - 클라이언트 인증서가 허용되며 제공된 경우 유효해야 하지만 필수는 아닙니다.

CLI에서 사용시

Verify the Redis Server Certificate:

openssl s_client -connect {REDIS_SERVER_HOSTNAME}:6379

Update Client Trust Store:

certutil -addstore -f "ROOT" path_to_server_certificate.crt

Configure redis-cli for SSL Connections:

redis-cli --tls --cacert /path/to/ca.crt -h hostname -p port

Update System Trust Store:

update-ca-certificates

Disable Certificate Validation (Not Recommended) - 짜증나면 걍 꺼버려라.

redis-cli --tls --insecure -h hostname -p port

redis.py 사용시

ssl_cert_reqs="none"옵션을 추가하면 인증일 스킵한다:

pool = redis.ConnectionPool(host=..., 
                            port=6380,
                            password=...,
                            db=0, 
                            connection_class=redis.SSLConnection, 
                            ssl_cert_reqs=u'none')
client = redis.Redis(connection_pool=pool)

Redis client handling

CLIENT command

  • CLIENT LIST
  • CLIENT KILL
  • CLIENT SETNAME
  • CLIENT GETNAME

Troubleshooting

사용자 명이 없을 경우

Upstash 같은곳 에서 사용자명이 없다면 공백으로 두던가 아니면 default 으로 하면 되는듯

MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk

aioredis에서 다음과 같은 에러 발생:

Oct 16 10:50:23 aaa python3.8[4037]: 2023-10-16 10:50:23.040 4037/140203648191360 aiohttp.access INFO 118.222.146.217 [16/Oct/2023:01:50:23 +0000] "GET /api/v2/plugins/a4y/default/default/devices/913 HTTP/1.1" 200 470 "http://219.254.103.36/app/main/default/default/a4y/details/913" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0"
Oct 16 10:50:24 aaa python3.8[4037]: 2023-10-16 10:50:24.027 4037/140203648191360 aiohttp.server ERROR Error handling request
Oct 16 10:50:24 aaa python3.8[4037]: Traceback (most recent call last):
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/aiohttp/web_protocol.py", line 433, in _handle_request
Oct 16 10:50:24 aaa python3.8[4037]:     resp = await request_handler(request)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/aiohttp/web_app.py", line 504, in _handle
Oct 16 10:50:24 aaa python3.8[4037]:     resp = await handler(request)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/home/storage/plugin/a4y/recc_plugin_a4y/a4y_main.py", line 892, in on_get_root
Oct 16 10:50:24 aaa python3.8[4037]:     uid = await self._receive_packet(request, ws, msg)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/home/storage/plugin/a4y/recc_plugin_a4y/a4y_main.py", line 791, in _receive_packet
Oct 16 10:50:24 aaa python3.8[4037]:     return await self._do_packet_processing(bytes.fromhex(hex_str))
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/home/storage/plugin/a4y/recc_plugin_a4y/a4y_main.py", line 803, in _do_packet_processing
Oct 16 10:50:24 aaa python3.8[4037]:     await self._update_to_cache(time, packet)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/home/storage/plugin/a4y/recc_plugin_a4y/a4y_main.py", line 837, in _update_to_cache
Oct 16 10:50:24 aaa python3.8[4037]:     await self.cache.set(key, data)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/recc-2.0.0.dev8-py3.8.egg/recc/cache/redis/redis_cache_store.py", line 94, in set
Oct 16 10:50:24 aaa python3.8[4037]:     await self.redis.execute_command("SET", key, val)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/aioredis/client.py", line 1085, in execute_command
Oct 16 10:50:24 aaa python3.8[4037]:     return await self.parse_response(conn, command_name, **options)
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/aioredis/client.py", line 1101, in parse_response
Oct 16 10:50:24 aaa python3.8[4037]:     response = await connection.read_response()
Oct 16 10:50:24 aaa python3.8[4037]:   File "/usr/local/recc/python/lib/python3.8/site-packages/aioredis/connection.py", line 919, in read_response
Oct 16 10:50:24 aaa python3.8[4037]:     raise response from None
Oct 16 10:50:24 aaa python3.8[4037]: aioredis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.

마지막줄 번역하면:

aioredis.Exceptions.ResponseError: MISCONF Redis가 RDB 스냅샷을 저장하도록 구성되어 있지만 현재 디스크에 유지할 수 없습니다. RDB 스냅샷 생성이 실패할 경우(stop-writes-on-bgsave-error 옵션) 쓰기 중에 오류를 보고하도록 이 인스턴스가 구성되어 있으므로 데이터 세트를 수정할 수 있는 명령이 비활성화됩니다. RDB 오류에 대한 자세한 내용은 Redis 로그를 확인하세요.

관련 설정 비활성화 방법:

$ redis-cli
> config set stop-writes-on-bgsave-error no

메모리 오버커밋 관련 이슈가 있는듯함

$ sudo sysctl -a | grep overcommit_memory
vm.overcommit_memory = 0

$ sudo sysctl vm.overcommit_memory=1

참고로 레디스 로그를 확인하면 관련된 내용이 있다:

1:M 13 Oct 2023 09:17:15.224 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

Failed opening the RDB file crontab (in server root dir /etc) for saving: Permission denied

...
1:M 14 Oct 2023 12:46:56.073 * 100 changes in 300 seconds. Saving...
1:M 14 Oct 2023 12:46:56.074 * Background saving started by pid 59050
59050:C 14 Oct 2023 12:46:56.074 # Failed opening the RDB file crontab (in server root dir /etc) for saving: Permission denied
1:M 14 Oct 2023 12:46:56.174 # Background saving error
1:M 14 Oct 2023 12:47:02.003 * 100 changes in 300 seconds. Saving...
1:M 14 Oct 2023 12:47:02.003 * Background saving started by pid 59057
59057:C 14 Oct 2023 12:47:02.003 # Failed opening the RDB file crontab (in server root dir /etc) for saving: Permission denied
1:M 14 Oct 2023 12:47:02.104 # Background saving error
1:M 14 Oct 2023 12:47:08.030 * 100 changes in 300 seconds. Saving...
1:M 14 Oct 2023 12:47:08.031 * Background saving started by pid 59058
59058:C 14 Oct 2023 12:47:08.031 # Failed opening the RDB file crontab (in server root dir /etc) for saving: Permission denied
...

/data, /etc 디렉토리 등 권한 문제.

chmod 777 -R /data  // for the data directory
chmod 777 -R /etc   // for etc folder.

READONLY You can't write against a read only replica

Possible SECURITY ATTACK detected

보안 이슈 Cross Protocol Scripting 공격인 'host:'와 'post' 명령(?)이 들어오면 securityWarningCommand() 이 실행되어 서버 로그에

# Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due t o an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted.

이런 메시지를 남기고 연결을 끊는 기능을 추가했습니다.

MASTER <-> REPLICA sync started

SSL_connect failed: certificate verify failed

CLI 에서 SSL 인증 오류가 발생할 경우

Could not connect to Redis at 127.0.0.1:16379: SSL_connect failed: certificate verify failed

클라이언트 인증을 사용하지 않을 경우 --insecure 옵션을 추가하면 된다:

redis-cli --tls -p 16379 --insecure -a {password} -h api.your.run

See also

Favorite site

Guide