运维开发实践 - Django Redis Sentinel

1. 背景

- django==3.2.15
- djangorestframework==3.13.1
- django-redis==5.2.0
- redis==4.5.1

当我们的Django需要使用redis sentinel模式时,会安装

pip install django-redis-sentinel

在实际使用时发现, django-redis-sentinel太久没更新,其与我们Django,django-redis之间不兼容;

2.解决方案

2.1. 手写django-redis-sentinel

2.1.1. redis_sentinel_client.py
# redis_sentinel_client.py
import logging
from typing import Any, Optional

from django_redis.client import DefaultClient


__LOG__ = logging.getLogger(__name__)

from django_redis.util import CacheKey

from redis.sentinel import Sentinel

class SentinelClient(DefaultClient):
    def __init__(self, server, params, backend):
        super(SentinelClient, self).__init__(server,params,backend)
        self._connection_string = server
        sentinel_kwargs = self._options.get("SENTINEL_KWARGS", None)
        master_name, sentinel_hosts, db = self.parse_connection_string(self._connection_string)
        sentinel = Sentinel(sentinels=sentinel_hosts, sentinel_kwargs=sentinel_kwargs)
        host, port = sentinel.discover_master(master_name)
        password = self._options.get("PASSWORD", None)
        self._server = list()
        self._server.append(self.ret_refis_connect_url(host, port, db, password))
        slaves = sentinel.discover_slaves(master_name)
        for host, port in slaves:
            self._server.append(self.ret_refis_connect_url(host, port, db, password))
        __LOG__.info("Finding {}".__format__(self._server))

    def ret_refis_connect_url(self, host, port, db, password):
        if password != None:
            return "redis://:%s@%s:%s/%s"%(password, host, port, db)
        return "redis://%s:%s/%s"%(host, port, db)

    def parse_connection_string(self, connstring):
        try:
            connection_params = connstring.split("/")
            # 我们约定将第一个redis host设为redis master
            master_name = connection_params[0]
            servers = [host_port.split(":") for host_port in connection_params[1].split(",")]
            sentinel_hosts = [(host, int(port)) for host,port in servers]
            db = connection_params[2]
        except (ValueError, TypeError, IndexError):
            raise Exception("Incorrect format '%s'"%(connstring))
        return master_name, sentinel_hosts, db
    
    def make_key(self, key: Any, version: Optional[Any] = None, prefix: Optional[str] = None):
        if prefix is None:
            prefix = self._backend.key_prefix
        return CacheKey('%s:%s'%(prefix, key))

2.1.2. settings.py
# settings.py
# redis master: 192.168.31.175:6379
# redis sentinel_01: 192.168.31.174:6379
# redis_sentinel_02: 192.168.31.173:6379
...
CACHES = {
	"default": {
		"BACKEND": "django_redis.cache.RedisCache",
		# 我们默认第一个host为redis master
		"LOCATION": "mymaster/192.168.31.175:6379,192.168.31.174:6379,192.168.31.173:6379/0",
		"OPTIONS": {
			"PASSWORD": os.environ.get("REDIS_PASSWORD"),
			"SENTINEL_KWARGS": {"password": os.environ.get("REDIS_SENTINEL_PASSWORD"), "socket_timeout": 3},
			"CLIENT_CLASS": "redis_sentinel_client.SentinelClient",
			"SERIALIZER": "django_redis.serializers.json.JSONSerializer"
		},
		"KEY_PREFIX": "liyuan"
	}
}

...

3. reference

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值