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
- redis-hkey-backup - Hash Key 기반 백업 및 복원 스크립트.
- node-redis (Javascript)
- redis-py
서비스 제공자
- Top 18 Managed Redis/Valkey Services Compared (May 2024)
- Upstash - 1초 1천 명령, 1일 1만 명령, 1달 50G 트래픽, 저장 공간 256MB
- Vercel KV
- Redis Ltd, (originally Redis Labs, Garantia Data; redislabs; Redis Cloud Console; Redis Cloud) - Free Tier 는 TLS 지원 안됨.
URL 만드는 방법
- 만약 사용자 명이 없을 경우 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 Lock - Redis
- Distributed Locks with Redis | Docs
- (Redis) 레디스가 제공하는 분산락(RedLock)의 특징과 한계 - MangKyu's Diary
- 레디스와 분산 락(1/2) - 레디스를 활용한 분산 락과 안전하고 빠른 락의 구현 | Hyperconnect Tech Blog
- Redisson, Jedis, Lettuce - 자바 레디스 클라이언트들
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개의 클라이언트가 수행한 명령 실행을 시뮬레이션하는 유틸리티가 포함되어 있습니다.
유틸리티는 기본 테스트 세트를 제공하거나 사용자 정의 테스트 세트를 제공할 수 있습니다.
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 Strings | Docs
- Redis 의 아이템의 크기 제한은 512MB입니다. | Charsyam's Blog
- celery - What is the maximum value size you can store in redis? - Stack Overflow
결론만 말하면 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이므로 크면 클수록 많은 데이터가 메모리에서 삭제되었다는 뜻입니다. |
그런데, 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 구성 파일 수정:
위의 구성은:
- Redis가 로컬에서만 접근 가능하도록 설정
- 보호 모드를 사용하도록 설정하며
- 기본 포트 6379를 사용하도록 합니다.
비밀번호를 사용한 Redis 인증을 설정하려면, Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다:
Redis TLS/SSL 보안을 구성하려면 OpenSSL을 설치하고 SSL 인증서 및 키를 생성해야 합니다. 자세한 내용은 OpenSSL 항목 참조.
Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다.
이제 Redis는 TLS/SSL로 암호화된 통신을 사용하여 접근할 수 있습니다.
백업 설정
Redis 데이터를 주기적으로 백업하려면 Redis 구성 파일을 열고 다음 구성 옵션을 추가합니다.
위의 구성은 Redis 데이터를 15분마다 백업하고, 최소 10개의 변경 사항이 있을 때마다 백업합니다. 또한 1시간마다 10000개의 변경 사항이 있을 때마다 백업합니다. - 확인 요망
Message Queue
Invalidation Message
레디스는 빠르지만, 잦은 데이터 조회는 API 서버에 부담을 줍니다. 특히 실시간 데이터처럼 갱신은 불규칙하지만 자주 조회해야 하는 경우, 효율적인 캐시 전략이 필요합니다.
- 문제점: Redis PubSub이나 Keyspace Notification은 갱신 감지 및 메시지 처리 로직이 복잡하거나 리소스 낭비를 유발할 수 있습니다.
- 해결책: Redis 6.0부터 지원하는 Invalidation Message는 서버가 클라이언트 캐시를 관리하는 방식입니다.
- 클라이언트가 키를 읽은 후 다른 클라이언트가 변경하면, Redis가 갱신 메시지를 보내 캐시를 삭제하도록 합니다.
- redigo+ristretto는 커스텀 로직이 필요하지만, rueidis는 DoCache 함수로 간단하게 구현 가능합니다.
Docker restart daemon 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만 활성화 하려면 다음과 같이 설정하면 된다.
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:
Update Client Trust Store:
Configure redis-cli for SSL Connections:
Update System Trust Store:
Disable Certificate Validation (Not Recommended) - 짜증나면 걍 꺼버려라.
redis.py 사용시
- SSL Connection Examples - redis-py dev documentation
- ConnectionError (SSL: CERTIFICATE_VERIFY_FAILED) when connecting to AWS ElastiCache over TLS · Issue #1080 · redis/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
- MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error. Resque
- MISCONF Redis is configured to save RDB snapshots - Stack Overflow
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 로그를 확인하세요.
관련 설정 비활성화 방법:
메모리 오버커밋 관련 이슈가 있는듯함
$ 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
디렉토리 등 권한 문제.
READONLY You can't write against a read only replica
- (Spring - Redis) READONLY You can't write against a read only replica.
- Docker on production , error - RedisException READONLY You can't write against a read only replica.
- (Redis) Failed opening .rdb for saving: Read-only file system :: 멋지게 놀아라
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 인증 오류가 발생할 경우
클라이언트 인증을 사용하지 않을 경우 --insecure
옵션을 추가하면 된다:
See also
- Memcached
- DynamoDB
- P3X Redis UI - GUI Client
- Redisinsight - GUI Client
- Dragonfly - Redis와 Memcached의 최신 대체제
- cachegrand - 최신 하드웨어에 잘 맞는 오픈소스 키-밸류 스토어
- KV.js - JS를 위한 고급 인메모리 캐슁 모듈
- broadcaster (python) - Simple broadcast channels
- Upstash - Redis 와 Kafka 서비스를 (제한된 무료) 제공해주는 클라우드 업체
- Keyv - Simple key-value storage with support for multiple backends
- Kronotop - Redis 호환 분산 문서 저장소, FoundationDB 기반
Favorite site
Guide
- Stackoverflow - Listen for changes in Redis? - 값이 변경되면 알림 받을 수 있는 기능?
- [추천] Redis 를 실무에 사용하기 전 꼭 알아야 하는 전략
- Redis 운영과 관리의 핵심: Redis 는 싱글 스레드다
- 서버에서는 Keys 명령을 사용하지 말자
- flushall/flushdb 명령을 주의하자
- Redis 운영과 관리의 핵심: Redis 는 싱글 스레드다
- AOF 와 RDB 의 기능 차이와 우선순위
- Redis 가 메모리를 두 배로 사용하는 문제