添加不使用Redis配置
This commit is contained in:
parent
f3ede6cb19
commit
8ad03fcbf2
26
QUICK_FIX.bat
Normal file
26
QUICK_FIX.bat
Normal file
@ -0,0 +1,26 @@
|
||||
@echo off
|
||||
echo ============================================================
|
||||
echo Fixing Redis Cache UTF-8 Decode Error
|
||||
echo ============================================================
|
||||
echo.
|
||||
|
||||
echo Step 1: Flushing Redis database 1...
|
||||
redis-cli -n 1 FLUSHDB
|
||||
echo Done!
|
||||
echo.
|
||||
|
||||
echo Step 2: Clearing Django cache...
|
||||
python manage.py clear_cache
|
||||
echo Done!
|
||||
echo.
|
||||
|
||||
echo Step 3: Reinitializing system config...
|
||||
python fix_cache.py
|
||||
echo Done!
|
||||
echo.
|
||||
|
||||
echo ============================================================
|
||||
echo Cache fixed! Now restart your Django server:
|
||||
echo python manage.py runserver
|
||||
echo ============================================================
|
||||
pause
|
||||
Binary file not shown.
@ -5,7 +5,41 @@ from django.db import connection
|
||||
from django.core.cache import cache
|
||||
from dvadmin.utils.validator import CustomValidationError
|
||||
|
||||
dispatch_db_type = getattr(settings, 'DISPATCH_DB_TYPE', 'redis') # redis
|
||||
# 检查是否使用Redis
|
||||
try:
|
||||
from conf.env import USE_REDIS
|
||||
except ImportError:
|
||||
USE_REDIS = getattr(settings, 'USE_REDIS', False)
|
||||
|
||||
dispatch_db_type = getattr(settings, 'DISPATCH_DB_TYPE', 'redis' if USE_REDIS else 'database') # 根据USE_REDIS自动选择
|
||||
|
||||
|
||||
def _delete_corrupted_cache_key(key):
|
||||
"""
|
||||
Delete a corrupted cache key using raw Redis client to bypass Django cache decode
|
||||
"""
|
||||
if not USE_REDIS:
|
||||
# 如果不是使用Redis,直接使用cache.delete
|
||||
cache.delete(key)
|
||||
return True
|
||||
|
||||
try:
|
||||
import redis
|
||||
from conf.env import REDIS_HOST, REDIS_PASSWORD, REDIS_DB
|
||||
if REDIS_PASSWORD:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB, password=REDIS_PASSWORD)
|
||||
else:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB)
|
||||
|
||||
# Use raw Redis delete to bypass Django's cache layer
|
||||
# Django adds a prefix, try both with and without
|
||||
deleted = r.delete(key)
|
||||
deleted += r.delete(f":1:{key}") # Django cache with version prefix
|
||||
print(f"Deleted {deleted} corrupted cache key(s) for: {key}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error deleting corrupted key {key}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def is_tenants_mode():
|
||||
@ -157,10 +191,20 @@ def get_dictionary_config(schema_name=None):
|
||||
:return:
|
||||
"""
|
||||
if dispatch_db_type == 'redis':
|
||||
init_dictionary_data = cache.get(f"init_dictionary")
|
||||
if not init_dictionary_data:
|
||||
try:
|
||||
init_dictionary_data = cache.get(f"init_dictionary")
|
||||
if not init_dictionary_data:
|
||||
refresh_dictionary()
|
||||
return cache.get(f"init_dictionary") or {}
|
||||
except (UnicodeDecodeError, Exception) as e:
|
||||
# Handle corrupted cache data - delete using raw Redis and refresh
|
||||
print(f"Cache decode error, clearing corrupted key: {e}")
|
||||
_delete_corrupted_cache_key("init_dictionary")
|
||||
refresh_dictionary()
|
||||
return cache.get(f"init_dictionary") or {}
|
||||
try:
|
||||
return cache.get(f"init_dictionary") or {}
|
||||
except:
|
||||
return {}
|
||||
if not settings.DICTIONARY_CONFIG:
|
||||
refresh_dictionary()
|
||||
if is_tenants_mode():
|
||||
@ -178,11 +222,22 @@ def get_dictionary_values(key, schema_name=None):
|
||||
:return:
|
||||
"""
|
||||
if dispatch_db_type == 'redis':
|
||||
dictionary_config = cache.get(f"init_dictionary")
|
||||
if not dictionary_config:
|
||||
refresh_dictionary()
|
||||
try:
|
||||
dictionary_config = cache.get(f"init_dictionary")
|
||||
return dictionary_config.get(key)
|
||||
if not dictionary_config:
|
||||
refresh_dictionary()
|
||||
dictionary_config = cache.get(f"init_dictionary")
|
||||
return dictionary_config.get(key)
|
||||
except (UnicodeDecodeError, Exception) as e:
|
||||
# Handle corrupted cache data - delete using raw Redis and refresh
|
||||
print(f"Cache decode error, clearing corrupted key: {e}")
|
||||
_delete_corrupted_cache_key("init_dictionary")
|
||||
refresh_dictionary()
|
||||
try:
|
||||
dictionary_config = cache.get(f"init_dictionary")
|
||||
return dictionary_config.get(key) if dictionary_config else None
|
||||
except:
|
||||
return None
|
||||
dictionary_config = get_dictionary_config(schema_name)
|
||||
return dictionary_config.get(key)
|
||||
|
||||
@ -214,10 +269,20 @@ def get_system_config(schema_name=None):
|
||||
:return:
|
||||
"""
|
||||
if dispatch_db_type == 'redis':
|
||||
init_dictionary_data = cache.get(f"init_system_config")
|
||||
if not init_dictionary_data:
|
||||
try:
|
||||
init_dictionary_data = cache.get(f"init_system_config")
|
||||
if not init_dictionary_data:
|
||||
refresh_system_config()
|
||||
return cache.get(f"init_system_config") or {}
|
||||
except (UnicodeDecodeError, Exception) as e:
|
||||
# Handle corrupted cache data - delete using raw Redis and refresh
|
||||
print(f"Cache decode error, clearing corrupted key: {e}")
|
||||
_delete_corrupted_cache_key("init_system_config")
|
||||
refresh_system_config()
|
||||
return cache.get(f"init_system_config") or {}
|
||||
try:
|
||||
return cache.get(f"init_system_config") or {}
|
||||
except:
|
||||
return {}
|
||||
if not settings.SYSTEM_CONFIG:
|
||||
refresh_system_config()
|
||||
if is_tenants_mode():
|
||||
@ -235,11 +300,22 @@ def get_system_config_values(key, schema_name=None):
|
||||
:return:
|
||||
"""
|
||||
if dispatch_db_type == 'redis':
|
||||
system_config = cache.get(f"init_system_config")
|
||||
if not system_config:
|
||||
refresh_system_config()
|
||||
try:
|
||||
system_config = cache.get(f"init_system_config")
|
||||
return system_config.get(key)
|
||||
if not system_config:
|
||||
refresh_system_config()
|
||||
system_config = cache.get(f"init_system_config")
|
||||
return system_config.get(key)
|
||||
except (UnicodeDecodeError, Exception) as e:
|
||||
# Handle corrupted cache data - delete using raw Redis and refresh
|
||||
print(f"Cache decode error, clearing corrupted key: {e}")
|
||||
_delete_corrupted_cache_key("init_system_config")
|
||||
refresh_system_config()
|
||||
try:
|
||||
system_config = cache.get(f"init_system_config")
|
||||
return system_config.get(key) if system_config else None
|
||||
except:
|
||||
return None
|
||||
system_config = get_system_config(schema_name)
|
||||
return system_config.get(key)
|
||||
|
||||
|
||||
@ -175,27 +175,39 @@ STATICFILES_FINDERS = (
|
||||
# ================================================= #
|
||||
# ******************* Redis缓存配置 ******************* #
|
||||
# ================================================= #
|
||||
# 根据是否有密码决定Redis URL格式
|
||||
if REDIS_PASSWORD:
|
||||
REDIS_CACHE_URL = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
else:
|
||||
REDIS_CACHE_URL = f"redis://{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
# 是否使用Redis,如果不使用Redis则使用本地内存缓存
|
||||
USE_REDIS = getattr(locals(), "USE_REDIS", False)
|
||||
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": REDIS_CACHE_URL,
|
||||
"OPTIONS": {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
"CONNECTION_POOL_KWARGS": {
|
||||
"max_connections": 100,
|
||||
"decode_responses": True
|
||||
},
|
||||
"SOCKET_CONNECT_TIMEOUT": 5, # 连接超时时间(秒)
|
||||
"SOCKET_TIMEOUT": 5, # 读写超时时间(秒)
|
||||
if USE_REDIS:
|
||||
# 使用Redis缓存
|
||||
if REDIS_PASSWORD:
|
||||
REDIS_CACHE_URL = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
else:
|
||||
REDIS_CACHE_URL = f"redis://{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": REDIS_CACHE_URL,
|
||||
"OPTIONS": {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
"CONNECTION_POOL_KWARGS": {
|
||||
"max_connections": 100,
|
||||
"decode_responses": True
|
||||
},
|
||||
"SOCKET_CONNECT_TIMEOUT": 5, # 连接超时时间(秒)
|
||||
"SOCKET_TIMEOUT": 5, # 读写超时时间(秒)
|
||||
}
|
||||
}
|
||||
}
|
||||
else:
|
||||
# 使用本地内存缓存(不使用Redis)
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
"LOCATION": "unique-snowflake",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ================================================= #
|
||||
# ******************* 跨域的配置 ******************* #
|
||||
@ -214,21 +226,26 @@ CORS_ALLOW_CREDENTIALS = True # 指明在跨域访问中,后端是否支持
|
||||
# ********************* channels配置 ******************* #
|
||||
# ===================================================== #
|
||||
ASGI_APPLICATION = 'application.asgi.application'
|
||||
# CHANNEL_LAYERS = {
|
||||
# "default": {
|
||||
# "BACKEND": "channels.layers.InMemoryChannelLayer"
|
||||
# }
|
||||
# }
|
||||
CHANNEL_LAYERS = {
|
||||
'default': {
|
||||
'BACKEND': 'channels_redis.core.RedisChannelLayer',
|
||||
'CONFIG': {
|
||||
"hosts": [(f'{REDIS_HOST}', 6379)],
|
||||
"password": REDIS_PASSWORD if REDIS_PASSWORD else None,
|
||||
"db": REDIS_DB,
|
||||
|
||||
# 根据是否使用Redis选择channel layer
|
||||
if USE_REDIS:
|
||||
CHANNEL_LAYERS = {
|
||||
'default': {
|
||||
'BACKEND': 'channels_redis.core.RedisChannelLayer',
|
||||
'CONFIG': {
|
||||
"hosts": [(f'{REDIS_HOST}', 6379)],
|
||||
"password": REDIS_PASSWORD if REDIS_PASSWORD else None,
|
||||
"db": REDIS_DB,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
else:
|
||||
# 不使用Redis,使用内存channel layer
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels.layers.InMemoryChannelLayer"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# ================================================= #
|
||||
@ -418,13 +435,23 @@ API_MODEL_MAP = {
|
||||
|
||||
DJANGO_CELERY_BEAT_TZ_AWARE = False
|
||||
CELERY_TIMEZONE = "Asia/Shanghai" # celery 时区问题
|
||||
# Celery配置 - 使用Redis作为broker和result backend
|
||||
if REDIS_PASSWORD:
|
||||
CELERY_BROKER_URL = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{CELERY_BROKER_DB}"
|
||||
CELERY_RESULT_BACKEND = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
# Celery配置 - 根据是否使用Redis选择broker和result backend
|
||||
if USE_REDIS:
|
||||
# 使用Redis作为broker和result backend
|
||||
if REDIS_PASSWORD:
|
||||
CELERY_BROKER_URL = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{CELERY_BROKER_DB}"
|
||||
CELERY_RESULT_BACKEND = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
else:
|
||||
CELERY_BROKER_URL = f"redis://{REDIS_HOST}:6379/{CELERY_BROKER_DB}"
|
||||
CELERY_RESULT_BACKEND = f"redis://{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
else:
|
||||
CELERY_BROKER_URL = f"redis://{REDIS_HOST}:6379/{CELERY_BROKER_DB}"
|
||||
CELERY_RESULT_BACKEND = f"redis://{REDIS_HOST}:6379/{REDIS_DB}"
|
||||
# 不使用Redis,使用Dummy broker(Celery将不会真正运行任务)
|
||||
# 如果需要真正的异步任务,请安装并配置RabbitMQ,或使用数据库作为broker
|
||||
CELERY_BROKER_URL = "amqp://guest@localhost//" # 需要RabbitMQ,如果没有则使用dummy
|
||||
CELERY_RESULT_BACKEND = "cache+memory://" # 使用内存存储结果
|
||||
# 注意:如果没有RabbitMQ,Celery任务将不会真正执行
|
||||
# 可以使用数据库作为broker:CELERY_BROKER_URL = "db+sqlite:///celery_broker.sqlite"
|
||||
# 但这需要安装kombu[db]或kombu[sqlalchemy]
|
||||
CELERY_ACCEPT_CONTENT = ['json']
|
||||
CELERY_TASK_SERIALIZER = 'json'
|
||||
CELERY_RESULT_SERIALIZER = 'json'
|
||||
|
||||
67
check_db.py
Normal file
67
check_db.py
Normal file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Check database for SystemConfig issues
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
# Setup Django environment
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
django.setup()
|
||||
|
||||
from dvadmin.system.models import SystemConfig
|
||||
|
||||
print("=" * 60)
|
||||
print("Checking SystemConfig Database")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
# Check if table exists and has data
|
||||
count = SystemConfig.objects.count()
|
||||
print(f"\n✓ SystemConfig table exists")
|
||||
print(f"✓ Found {count} records")
|
||||
|
||||
if count == 0:
|
||||
print("\n⚠ WARNING: No system config records found!")
|
||||
print(" You may need to run: python manage.py init")
|
||||
else:
|
||||
# Check for problematic records
|
||||
print("\nChecking for problematic records...")
|
||||
configs = SystemConfig.objects.filter(parent_id__isnull=False).values(
|
||||
'id', 'parent__key', 'key', 'value', 'form_item_type'
|
||||
)[:10]
|
||||
|
||||
print(f"\nFirst 10 config records:")
|
||||
for config in configs:
|
||||
key_name = f"{config.get('parent__key')}.{config.get('key')}"
|
||||
value = config.get('value')
|
||||
print(f" - {key_name}: {type(value).__name__} = {str(value)[:50]}...")
|
||||
|
||||
# Try to build the config dict like dispatch does
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing config building (like dispatch.py does)...")
|
||||
print("=" * 60)
|
||||
|
||||
from application.dispatch import _get_all_system_config
|
||||
try:
|
||||
data = _get_all_system_config()
|
||||
print(f"\n✓ Successfully built config dict with {len(data)} keys")
|
||||
print("\nSample keys:")
|
||||
for i, (k, v) in enumerate(list(data.items())[:5]):
|
||||
print(f" - {k}: {type(v).__name__}")
|
||||
if i >= 4:
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"\n✗ ERROR building config: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ ERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
@ -28,6 +28,10 @@ TABLE_PREFIX = "dvadmin_"
|
||||
# ================================================= #
|
||||
# ******** redis配置,无redis 可不进行配置 ******** #
|
||||
# ================================================= #
|
||||
# 是否使用Redis,设置为False则不使用Redis(使用本地内存缓存和数据库)
|
||||
USE_REDIS = False
|
||||
|
||||
# 以下Redis配置仅在USE_REDIS=True时生效
|
||||
REDIS_DB = 1
|
||||
CELERY_BROKER_DB = 3
|
||||
REDIS_PASSWORD = 'DVADMIN3'
|
||||
|
||||
@ -28,6 +28,10 @@ TABLE_PREFIX = "dvadmin_"
|
||||
# ================================================= #
|
||||
# ******** redis配置,无redis 可不进行配置 ******** #
|
||||
# ================================================= #
|
||||
# 是否使用Redis,设置为False则不使用Redis(使用本地内存缓存和数据库)
|
||||
USE_REDIS = False
|
||||
|
||||
# 以下Redis配置仅在USE_REDIS=True时生效
|
||||
REDIS_DB = 1
|
||||
CELERY_BROKER_DB = 3
|
||||
REDIS_PASSWORD = '' # 无密码的Redis服务器
|
||||
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
17
dvadmin/system/management/commands/clear_cache.py
Normal file
17
dvadmin/system/management/commands/clear_cache.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Clear Django cache to fix UTF-8 decode errors
|
||||
"""
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Clear Django cache (useful for fixing UTF-8 decode errors)'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
try:
|
||||
cache.clear()
|
||||
self.stdout.write(self.style.SUCCESS('Successfully cleared cache!'))
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.ERROR(f'Failed to clear cache: {e}'))
|
||||
112
fix_cache.py
Normal file
112
fix_cache.py
Normal file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Fix corrupted Redis cache by deleting specific keys
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
# Setup Django environment
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
django.setup()
|
||||
|
||||
import redis
|
||||
from conf.env import REDIS_HOST, REDIS_PASSWORD, REDIS_DB
|
||||
|
||||
def fix_cache():
|
||||
"""Delete corrupted cache keys"""
|
||||
try:
|
||||
# Create Redis connection
|
||||
if REDIS_PASSWORD:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB, password=REDIS_PASSWORD)
|
||||
else:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB)
|
||||
|
||||
print("=" * 60)
|
||||
print("Fixing corrupted Redis cache...")
|
||||
print("=" * 60)
|
||||
|
||||
# List of keys that might be corrupted
|
||||
problem_keys = [
|
||||
'init_system_config',
|
||||
'init_dictionary',
|
||||
':1:init_system_config',
|
||||
':1:init_dictionary',
|
||||
]
|
||||
|
||||
deleted_count = 0
|
||||
for key in problem_keys:
|
||||
try:
|
||||
# Try to get the key
|
||||
exists = r.exists(key)
|
||||
if exists:
|
||||
print(f"\n✓ Found key: {key}")
|
||||
# Try to decode it
|
||||
try:
|
||||
value = r.get(key)
|
||||
if value:
|
||||
# Try to decode as UTF-8
|
||||
value.decode('utf-8')
|
||||
print(f" → Key is OK (can be decoded)")
|
||||
except UnicodeDecodeError:
|
||||
print(f" → Key is CORRUPTED (UTF-8 decode error)")
|
||||
r.delete(key)
|
||||
print(f" → DELETED corrupted key")
|
||||
deleted_count += 1
|
||||
except Exception as e:
|
||||
print(f" → Error checking key: {e}")
|
||||
r.delete(key)
|
||||
print(f" → DELETED problematic key")
|
||||
deleted_count += 1
|
||||
except Exception as e:
|
||||
print(f"✗ Error processing key {key}: {e}")
|
||||
|
||||
# Also clear all keys with pattern
|
||||
print("\n" + "=" * 60)
|
||||
print("Searching for all cache keys...")
|
||||
all_keys = r.keys('*')
|
||||
print(f"Found {len(all_keys)} total keys in Redis DB {REDIS_DB}")
|
||||
|
||||
if all_keys:
|
||||
print("\nChecking all keys for corruption...")
|
||||
for key in all_keys:
|
||||
try:
|
||||
key_str = key.decode('utf-8') if isinstance(key, bytes) else key
|
||||
value = r.get(key)
|
||||
if value:
|
||||
try:
|
||||
value.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
print(f" → Corrupted key found: {key_str}")
|
||||
r.delete(key)
|
||||
deleted_count += 1
|
||||
print(f" → DELETED")
|
||||
except Exception as e:
|
||||
print(f" → Error with key: {e}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print(f"✓ Fixed! Deleted {deleted_count} corrupted keys")
|
||||
print("=" * 60)
|
||||
|
||||
# Now reinitialize the cache
|
||||
print("\nReinitializing system config...")
|
||||
from application import dispatch
|
||||
dispatch.refresh_system_config()
|
||||
dispatch.refresh_dictionary()
|
||||
print("✓ System config reinitialized!")
|
||||
|
||||
return True
|
||||
except redis.ConnectionError as e:
|
||||
print(f"✗ Redis connection failed: {e}")
|
||||
print(" Make sure Redis server is running")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
fix_cache()
|
||||
4596
logs/error.log
4596
logs/error.log
File diff suppressed because it is too large
Load Diff
4963
logs/server.log
4963
logs/server.log
File diff suppressed because it is too large
Load Diff
79
test_redis.py
Normal file
79
test_redis.py
Normal file
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Test Redis connection and clear cache if needed
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
# Setup Django environment
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
django.setup()
|
||||
|
||||
from django.core.cache import cache
|
||||
import redis
|
||||
|
||||
def test_redis_connection():
|
||||
"""Test if Redis is accessible"""
|
||||
try:
|
||||
from conf.env import REDIS_HOST, REDIS_PASSWORD, REDIS_DB
|
||||
|
||||
# Create Redis connection
|
||||
if REDIS_PASSWORD:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB, password=REDIS_PASSWORD, decode_responses=True)
|
||||
else:
|
||||
r = redis.Redis(host=REDIS_HOST, port=6379, db=REDIS_DB, decode_responses=True)
|
||||
|
||||
# Test connection
|
||||
response = r.ping()
|
||||
print(f"✓ Redis connection successful: {response}")
|
||||
|
||||
# Get all keys
|
||||
keys = r.keys('*')
|
||||
print(f"✓ Found {len(keys)} keys in Redis database {REDIS_DB}")
|
||||
|
||||
if keys:
|
||||
print("\nKeys in Redis:")
|
||||
for key in keys[:10]: # Show first 10 keys
|
||||
print(f" - {key}")
|
||||
if len(keys) > 10:
|
||||
print(f" ... and {len(keys) - 10} more")
|
||||
|
||||
return True
|
||||
except redis.ConnectionError as e:
|
||||
print(f"✗ Redis connection failed: {e}")
|
||||
print(" Make sure Redis server is running: redis-server")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {e}")
|
||||
return False
|
||||
|
||||
def clear_django_cache():
|
||||
"""Clear Django cache"""
|
||||
try:
|
||||
cache.clear()
|
||||
print("\n✓ Django cache cleared successfully!")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"\n✗ Failed to clear Django cache: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("=" * 60)
|
||||
print("Redis Connection Test & Cache Clear Utility")
|
||||
print("=" * 60)
|
||||
|
||||
if test_redis_connection():
|
||||
print("\n" + "=" * 60)
|
||||
choice = input("\nDo you want to clear the Django cache? (y/n): ").lower()
|
||||
if choice == 'y':
|
||||
clear_django_cache()
|
||||
else:
|
||||
print("Cache not cleared.")
|
||||
else:
|
||||
print("\n⚠ Cannot clear cache - Redis connection failed")
|
||||
print("Please start Redis server first: redis-server")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
150
不使用Redis配置说明.md
Normal file
150
不使用Redis配置说明.md
Normal file
@ -0,0 +1,150 @@
|
||||
# 不使用Redis的配置说明
|
||||
|
||||
## 概述
|
||||
|
||||
本项目支持两种运行模式:
|
||||
1. **使用Redis模式** - 生产环境推荐,提供分布式缓存和更好的性能
|
||||
2. **不使用Redis模式** - 开发/测试环境推荐,使用本地内存缓存,无需安装Redis
|
||||
|
||||
## 配置方式
|
||||
|
||||
### 不使用Redis配置
|
||||
|
||||
在 `conf/env.py` 文件中,将 `USE_REDIS` 设置为 `False`:
|
||||
|
||||
```python
|
||||
# ================================================= #
|
||||
# ******** redis配置,无redis 可不进行配置 ******** #
|
||||
# ================================================= #
|
||||
# 是否使用Redis,设置为False则不使用Redis(使用本地内存缓存和数据库)
|
||||
USE_REDIS = False # 设置为False
|
||||
|
||||
# 以下Redis配置仅在USE_REDIS=True时生效
|
||||
REDIS_DB = 1
|
||||
CELERY_BROKER_DB = 3
|
||||
REDIS_PASSWORD = ''
|
||||
REDIS_HOST = '127.0.0.1'
|
||||
```
|
||||
|
||||
### 使用Redis配置
|
||||
|
||||
如果需要使用Redis,将 `USE_REDIS` 设置为 `True`:
|
||||
|
||||
```python
|
||||
USE_REDIS = True # 设置为True
|
||||
|
||||
# 配置Redis连接信息
|
||||
REDIS_DB = 1
|
||||
CELERY_BROKER_DB = 3
|
||||
REDIS_PASSWORD = 'your_password' # Redis密码,无密码则留空
|
||||
REDIS_HOST = '127.0.0.1' # Redis服务器地址
|
||||
```
|
||||
|
||||
## 不同配置下的行为
|
||||
|
||||
### 1. 缓存系统
|
||||
|
||||
| 配置 | 缓存后端 | 说明 |
|
||||
|------|---------|------|
|
||||
| `USE_REDIS = False` | `django.core.cache.backends.locmem.LocMemCache` | 本地内存缓存 |
|
||||
| `USE_REDIS = True` | `django_redis.cache.RedisCache` | Redis分布式缓存 |
|
||||
|
||||
**注意**:本地内存缓存在多进程部署环境下不共享,重启后数据会丢失。
|
||||
|
||||
### 2. Channels(WebSocket/SSE)
|
||||
|
||||
| 配置 | Channel Layer | 说明 |
|
||||
|------|--------------|------|
|
||||
| `USE_REDIS = False` | `channels.layers.InMemoryChannelLayer` | 内存通道层 |
|
||||
| `USE_REDIS = True` | `channels_redis.core.RedisChannelLayer` | Redis通道层 |
|
||||
|
||||
**注意**:内存通道层在多实例部署环境下不支持跨实例通信。
|
||||
|
||||
### 3. Celery异步任务
|
||||
|
||||
| 配置 | Broker | Result Backend | 说明 |
|
||||
|------|--------|---------------|------|
|
||||
| `USE_REDIS = False` | `amqp://guest@localhost//` | `cache+memory://` | 需要RabbitMQ |
|
||||
| `USE_REDIS = True` | `redis://...` | `redis://...` | Redis作为broker和backend |
|
||||
|
||||
**注意**:
|
||||
- 不使用Redis时,Celery需要RabbitMQ作为broker
|
||||
- 如果项目不使用Celery异步任务,可以忽略此配置
|
||||
- 可以使用数据库作为broker(需要额外配置)
|
||||
|
||||
### 4. 系统配置和字典缓存
|
||||
|
||||
| 配置 | 存储方式 | 说明 |
|
||||
|------|---------|------|
|
||||
| `USE_REDIS = False` | 从数据库读取 | 每次查询数据库 |
|
||||
| `USE_REDIS = True` | Redis缓存 | 首次查询后缓存到Redis |
|
||||
|
||||
## 部署建议
|
||||
|
||||
### 开发/测试环境
|
||||
```python
|
||||
USE_REDIS = False # 推荐,简化环境配置
|
||||
```
|
||||
|
||||
### 单机生产环境
|
||||
```python
|
||||
USE_REDIS = False # 可接受,但建议使用Redis以提高性能
|
||||
```
|
||||
|
||||
### 多实例/分布式生产环境
|
||||
```python
|
||||
USE_REDIS = True # 必需,确保多实例间数据共享
|
||||
```
|
||||
|
||||
## 性能对比
|
||||
|
||||
| 场景 | 不使用Redis | 使用Redis |
|
||||
|------|-----------|----------|
|
||||
| 缓存查询速度 | 快(内存) | 快(内存+网络) |
|
||||
| 多实例数据共享 | ❌ 不支持 | ✅ 支持 |
|
||||
| 缓存持久化 | ❌ 不支持 | ✅ 支持(可配置) |
|
||||
| 部署复杂度 | ✅ 简单 | ⚠️ 需要部署Redis |
|
||||
| 成本 | ✅ 免费 | ⚠️ 需要服务器资源 |
|
||||
|
||||
## 切换配置
|
||||
|
||||
1. 修改 `conf/env.py` 中的 `USE_REDIS` 配置
|
||||
2. 重启Django服务
|
||||
3. 如果从Redis切换到非Redis,建议清理之前的Redis缓存
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题:项目启动报错,提示Redis连接失败
|
||||
|
||||
**解决方案**:
|
||||
- 检查 `USE_REDIS` 是否正确设置为 `False`
|
||||
- 确认 `conf/env.py` 文件已保存
|
||||
|
||||
### 问题:多用户环境下缓存不同步
|
||||
|
||||
**解决方案**:
|
||||
- 如果在多实例部署环境,必须使用Redis
|
||||
- 将 `USE_REDIS` 设置为 `True` 并配置Redis服务器
|
||||
|
||||
### 问题:Celery任务无法执行
|
||||
|
||||
**解决方案**:
|
||||
- 检查是否安装了RabbitMQ或Redis
|
||||
- 确认Celery worker是否正在运行
|
||||
- 不使用异步任务时,可以忽略Celery相关配置
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `conf/env.py` - 环境配置文件
|
||||
- `conf/env.example.py` - 环境配置示例文件
|
||||
- `application/settings.py` - Django主配置文件
|
||||
- `application/dispatch.py` - 缓存相关工具函数
|
||||
|
||||
## 依赖说明
|
||||
|
||||
不使用Redis时,以下依赖仍然需要安装(用于其他功能):
|
||||
- `django-redis==5.4.0` - Redis支持库(可选依赖)
|
||||
- `channels-redis==4.2.0` - Channels Redis支持(可选依赖)
|
||||
- `redis` - Redis客户端库(可选依赖)
|
||||
|
||||
这些依赖只在 `USE_REDIS = True` 时才会被使用。
|
||||
Loading…
Reference in New Issue
Block a user