近期改造一个基于 django 3.2 的后端服务,把单点 redis 换为 redis sentinel 集群时发生了一些问题,记录下来:

最终的 settings.py 内关于 redis 的配置如下
# 单点服务配置
REDIS = {
    'HOST': 'redis-node-0.redis-headless.infra',  # k8s 内的按索引找到 redis 节点 0
    'PORT': 6389,
    'PASSWORD': '',
    'DB': '0',          # redis 一个实例有 16 个数据库,分别为:0 ~ 15,默认为 0
    'SENTINEL': False,  # 是否使用 sentinel 集群
    'SENTINEL_SERVICE_NAME': 'mymaster', # 集群下的服务名
}
# sentinel 集群服务配置
REDIS = {
    'HOST': 'redis.infra',
    'PORT': 26389,       # sentinel 集群一般使用 26379 端口
    'PASSWORD': 'xxxx',
    'DB': '1',          # redis 一个实例有 16 个数据库,分别为:0 ~ 15,默认为 0
    'SENTINEL': True,  # 是否使用 sentinel 集群
    'SENTINEL_SERVICE_NAME': 'mymaster', # 集群下的服务名
}

CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": f"redis://{REDIS['HOST']}:{REDIS['PORT']}/{REDIS['DB']}",
            "KEY_PREFIX": '',
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 20},
                "PASSWORD": REDIS['PASSWORD'],
            },
        }
    }
    if REDIS['SENTINEL']:
        # @see https://github.com/jazzband/django-redis#use-the-sentinel-connection-factory
        DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.SentinelConnectionFactory'
        CACHES['default']['LOCATION'] = f"redis://{REDIS['SENTINEL_SERVICE_NAME']}/{REDIS['DB']}",
        CACHES['default']['OPTIONS'].update(
            CLIENT_CLASS='django_redis.client.SentinelClient',
            SENTINELS=[(REDIS['HOST'], int(REDIS['PORT']))],
            SENTINEL_KWARGS=dict(password=REDIS['PASSWORD']),
            )
CACHE_SECONDS = 60 * 15
开发环境(requirements.txt)
django==3.2.8
django-redis==5.2.0
...
注意事项

试验密码支持时,找了不少资料,下面附带上如何测试 redis sentinel 集群的简化脚本:

# contest-backend-7d9b77b879-f56vz 是 django 后端服务的 pod 名字
kubectl -n weather-efusion exec -it contest-backend-7d9b77b879-f56vz -- python3
from redis.sentinel import Sentinel
sentinel = Sentinel([('redis.infra', 26379)], sentinel_kwargs=dict(password='xxxx'), socket_timeout=0.2)
print(sentinel.discover_master('mymaster'))
print(sentinel.discover_slaves('mymaster'))
master = sentinel.master_for('mymaster', socket_timeout=0.2, password='xxxx')
master.set('foo', 'bar')
slave = sentinel.slave_for('mymaster', socket_timeout=0.2, password='xxxx')
slave.get('foo')
master.delete('foo')
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐