0.リファレンス
DjangoでRedisを使用する方法は2つあります。
- カスタムモード
- サードパーティのコンポーネントを使用する[推奨]
1.カスタムモード
このようにして、Djangoを使用できるだけでなく、他のフレームワークやネイティブPythonも使用できます。
A.依存関係をインストールします
pip install redis
B.Redis構成
モジュールにカプセル化され、グローバルに使用できます
import redis
# 抽取封装成模块,全局使用(单例模式,redis_pool.py)
POOL = redis.ConnectionPool(host='xx.xx.xx.xx', port=6379, password='xxx', max_connections=1000)
c。使用
# 引用全局连接池
from redis_pool import POOL
conn = redis.Redis(connection_pool=POOL)
conn.set(key, value)
2.サードパーティコンポーネントの使用
Djangoの場合は、この方法を使用することをお勧めします
A.依存関係をインストールします
pip install django-redis
B. Redis構成(settings.py)
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {
"max_connections": 100, 'decode_responses': True},
# "PASSWORD": "密码",
},
# 前缀
"KEY_PREFIX": "test"
}
}
注:max_connectionsは接続プールです。不要な場合は削除できます
。注:プレフィックスは個人のニーズによって異なります。
-8、この設定を追加すると、読み取り時にデコードする必要がありません。ただし、decode_responsesがTrueに設定されている場合、以下の2番目の方法を使用してキャッシュを読み取ると、エラーが報告されます。
次に例を示します。
>>> from django_redis import get_redis_connection
>>> conn = get_redis_connection()
>>> conn.set('redis_test3', 22)
True
>>> conn.get('redis_test3')
b'22'
注:複数のRedisがある場合は、CACHEに新しいRedisを追加できます。これは、デフォルトとは異なります。
c。使用
2つの方法があります:
- get_redis_connection
- キャッシュ
最初の方法:get_redis_connection
はこの方法を推奨しています
from django_redis import get_redis_connection
# 这里可以传使用哪个redis,不传默认是default
redis = get_redis_connection()
redis.get(key)
redis.set(key, value)
注:decode_responsesがTrueに設定されていない場合、get_redis_connectionを使用して読み取られるデータはバイトであり、utf-8にデコードする必要があります。この設定を追加する場合、自分でデコードする必要はありません。
例:
>>> from django_redis import get_redis_connection
>>> conn = get_redis_connection()
>>> conn.set('redis_test3', 22)
True
>>> conn.get('redis_test3')
b'22'
注:この方法を使用すると、キャッシュ内のプレフィックスは有効になりません。つまり、redisに設定されている場合、キーはそのままで、プレフィックスは自動的に追加されません。
2番目の方法:キャッシュ
from django.core.cache import cache
cache.get(key)
cache.set(key, value)
注:キャッシュ内のdecode_responsesがTrueに設定されている場合、読み取りはエラーを報告します
>>> cache.get('redis_test3')
Traceback (most recent call last):
File "c:\users\jiand\appdata\local\programs\python\python37\Lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "D:\Python\Envs\Django2Demo\lib\site-packages\django_redis\cache.py", line 87, in get
value = self._get(key, default, version, client)
File "D:\Python\Envs\Django2Demo\lib\site-packages\django_redis\cache.py", line 27, in _decorator
return method(self, *args, **kwargs)
File "D:\Python\Envs\Django2Demo\lib\site-packages\django_redis\cache.py", line 94, in _get
return self.client.get(key, default=default, version=version, client=client)
File "D:\Python\Envs\Django2Demo\lib\site-packages\django_redis\client\default.py", line 220, in get
value = client.get(key)
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\client.py", line 1579, in get
return self.execute_command('GET', name)
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\client.py", line 878, in execute_command
return self.parse_response(conn, command_name, **options)
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\client.py", line 892, in parse_response
response = connection.read_response()
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\connection.py", line 734, in read_response
response = self._parser.read_response()
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\connection.py", line 358, in read_response
response = self.encoder.decode(response)
File "D:\Python\Envs\Django2Demo\lib\site-packages\redis\connection.py", line 129, in decode
value = value.decode(self.encoding, self.encoding_errors)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
概要:
これら2つの方法のいずれかを選択できます。1つを使用することをお勧めします。get_redis_connectionを使用し、キャッシュのdecode_responsesをTrueに設定することをお勧めします。
両方の方法を使用する必要がある場合は、decode_responsesの構成をから削除してください。キャッシュしてから、get_redis_connectionを使用してバイトを文字列に変換するときに読み取ります。
redis_value = self.conn.get(lock_name)
# 注意:如果是get_redis_connection的话,从redis里面读取的是bytes字符的
redis_value = redis_value.decode('utf-8') if isinstance(redis_value, bytes) else redis_value
サンプルコード
from django_redis import get_redis_connection
def get_private_ips(self, subnet_id, is_ignore_cache=False):
"""
查询私有IP列表
使用Redis缓存,保存1小时
:param subnet_id:
:param is_ignore_cache: 是否忽略缓存 默认是否
:return:
"""
key = 'HW_private_ips_area_%s_subnetId_%s' % (self.area, subnet_id)
cache = get_redis_connection()
# 保存1小时
expired_time = 60 * 60 * 1
res = cache.get(key, None)
if not res or is_ignore_cache:
sig = self.sig
uri = "/v1/{0}/subnets/{1}/privateips".format(sig.ProjectId, subnet_id)
res = self._hw_request(uri)
if res and not res.get('code') and res.get('privateips'):
cache.set(key, res, expired_time)
return res
単純なRedisロックの実装:
from django_redis import get_redis_connection
class LockService:
def __init__(self, conn=None):
"""
如果不传连接池的话,默认读取配置的Redis作为连接池
:param conn:
"""
self.conn = conn if conn else get_redis_connection()
def acquire_lock(self, lock_name, value, expire_time=60):
"""
加锁
如果不存在lock_name,则创建,并且设置过期时间,避免死锁
如果存在lock_name,则刷新过期时间
插入成功:返回True
已存在:返回False并且刷新过期时间
:param lock_name:
:param value:
:param expire_time:
:return:
"""
if self.conn.setnx(lock_name, value):
# 注意:Todo 这里可能会有问题,如果程序在写入redis之后但未设置有效期之前突然崩溃,则无法设置过期时间,将发生死锁
self.conn.expire(lock_name, expire_time)
return True
elif self.conn.ttl(lock_name):
self.conn.expire(lock_name, expire_time)
return False
def release_lock(self, lock_name, value):
"""
释放锁
注意:只有value值一致才会删除,避免在并发下删除了其他进程/线程设置的锁
:param lock_name:
:param value:
:return:
"""
redis_value = self.conn.get(lock_name)
# 注意:如果是get_redis_connection的话,从redis里面读取的是bytes字符的
redis_value = redis_value.decode('utf-8') if isinstance(redis_value, bytes) else redis_value
if str(redis_value) == str(value):
self.conn.delete(lock_name)