程序员必知的网站,百姓网招聘,最佳网页制作软件,营业执照名称查询系统一、为什么使用Redis缓存#xff1f;
在Django项目中#xff0c;Redis缓存可以#xff1a;
提升性能#xff1a;减少数据库查询降低负载#xff1a;分担数据库压力共享会话#xff1a;适合多服务器部署存储临时数据#xff1a;如验证码、短信限制
二、快速开始
1. 安装R…一、为什么使用Redis缓存在Django项目中Redis缓存可以提升性能减少数据库查询降低负载分担数据库压力共享会话适合多服务器部署存储临时数据如验证码、短信限制二、快速开始1. 安装Redis服务器Ubuntu/Debian:sudoaptupdatesudoaptinstallredis-serversudosystemctl start redissudosystemctlenableredis检查Redis是否运行:redis-cliping# 返回 PONG 表示成功2. 安装Python包pipinstalldjango-redis redis3. 基本配置在settings.py中添加# 缓存配置CACHES{default:{BACKEND:django_redis.cache.RedisCache,LOCATION:redis://127.0.0.1:6379/0,# 0号数据库OPTIONS:{CLIENT_CLASS:django_redis.client.DefaultClient,},TIMEOUT:60*15,# 默认15分钟过期}}# 可选将Session也存到RedisSESSION_ENGINEdjango.contrib.sessions.backends.cacheSESSION_CACHE_ALIASdefault三、基本使用1. 简单缓存操作from django.core.cacheimportcache from django.httpimportJsonResponseimporttimedef cache_demo(request):基本缓存操作示例# 1. 设置缓存缓存5分钟cache.set(username,张三,timeout300)# 2. 获取缓存usernamecache.get(username)# 如果不存在返回默认值usernamecache.get(username,默认用户)# 3. 设置多个值cache.set_many({key1:value1,key2:value2,key3:value3})# 4. 获取多个值valuescache.get_many([key1,key2,key3])# 5. 删除缓存cache.delete(key1)cache.delete_many([key2,key3])# 6. 只有键不存在时才设置cache.add(counter,1)# 第一次设置成功cache.add(counter,2)# 不会覆盖counter还是1# 7. 数字递增递减cache.set(visits,0)cache.incr(visits)# visits 1cache.incr(visits,10)# visits 11cache.decr(visits,5)# visits 6# 8. 清空所有缓存谨慎使用# cache.clear()returnJsonResponse({username:username})2. 缓存数据库查询结果from django.core.cacheimportcache from django.httpimportJsonResponse from .modelsimportArticleimportjson def get_articles(request): 获取文章列表使用缓存减少数据库查询 cache_keyarticle_list# 缓存键articlescache.get(cache_key)ifarticles is None:# 缓存中没有从数据库查询print(从数据库查询文章...)articleslist(Article.objects.filter(is_publishedTrue).values(id,title,created_at)[:10])# 将结果存入缓存有效期5分钟cache.set(cache_key, articles,timeout300)else: print(从缓存获取文章...)returnJsonResponse({articles:articles})3. 缓存用户数据from django.contrib.auth.decoratorsimportlogin_required from django.core.cacheimportcache from django.httpimportJsonResponse login_required def get_user_profile(request): 获取用户资料带用户ID的缓存 user_idrequest.user.id cache_keyfuser_profile:{user_id}# 尝试从缓存获取profilecache.get(cache_key)ifprofile is None:# 模拟获取用户资料数据库查询、API调用等print(f查询用户 {user_id} 的资料...)profile{id:user_id,username:request.user.username,email:request.user.email,last_login:request.user.last_login.isoformat()ifrequest.user.last_loginelseNone}# 缓存用户资料1小时cache.set(cache_key, profile,timeout3600)returnJsonResponse(profile)四、视图缓存1. 缓存整个视图from django.views.decorators.cacheimportcache_page from django.utils.decoratorsimportmethod_decorator from django.viewsimportView from django.httpimportJsonResponseimporttime# 函数视图缓存cache_page(60*5)# 缓存5分钟def expensive_view(request):耗时的视图缓存5分钟 time.sleep(2)# 模拟耗时操作returnJsonResponse({data:耗时操作结果,time:time.time()})# 类视图缓存class CachedView(View): method_decorator(cache_page(60*10))# 缓存10分钟def dispatch(self, *args, **kwargs):returnsuper().dispatch(*args, **kwargs)def get(self, request): time.sleep(1)# 模拟耗时操作returnJsonResponse({message:类视图缓存示例})2. 不缓存特定视图from django.views.decorators.cacheimportnever_cache from django.httpimportJsonResponse never_cache def sensitive_data_view(request):敏感数据不缓存returnJsonResponse({sensitive:这是敏感数据})五、模板缓存在模板中使用缓存!-- article_detail.html --{% load cache %}h1{{article.title}}/h1!-- 缓存侧边栏5分钟 --{% cache300sidebar %}divclasssidebarh3热门文章/h3ul{%forhot_articleinhot_articles %}li{{hot_article.title}}/li{% endfor %}/ul/div{% endcache %}!-- 根据用户缓存不同用户看到不同内容 --{% cache300user_specific request.user.id %}divclassuser-infoh3欢迎{{request.user.username}}/h3!-- 用户特定内容 --/div{% endcache %}!-- 根据文章ID和更新时间缓存 --{% cache300article_content article.id article.updated_at %}divclasscontent{{article.content|safe}}/div{% endcache %}六、实战案例商品列表页1. 模型# models.pyfrom django.dbimportmodels class Product(models.Model): namemodels.CharField(max_length100)pricemodels.DecimalField(max_digits10,decimal_places2)stockmodels.IntegerField(default0)created_atmodels.DateTimeField(auto_now_addTrue)updated_atmodels.DateTimeField(auto_nowTrue)def __str__(self):returnself.name2. 带缓存的商品服务# services/product_service.pyfrom django.core.cacheimportcache from .modelsimportProductimportjson from datetimeimportdatetime class ProductService:商品服务包含缓存逻辑 staticmethod def get_products(categoryNone,limit20): 获取商品列表带缓存# 生成缓存键cache_keyproductsifcategory: cache_keyfproducts:{category}# 尝试从缓存获取productscache.get(cache_key)ifproducts is None:# 查询数据库querysetProduct.objects.filter(stock__gt0)ifcategory: querysetqueryset.filter(categorycategory)productslist(queryset.values(id,name,price,stock)[:limit])# 存入缓存10分钟cache.set(cache_key, products,timeout600)returnproducts staticmethod def get_product_detail(product_id): 获取商品详情带缓存 cache_keyfproduct_detail:{product_id}productcache.get(cache_key)ifproduct is None: try: product_objProduct.objects.get(idproduct_id)product{id:product_obj.id,name:product_obj.name,price:float(product_obj.price),stock:product_obj.stock,description:getattr(product_obj,description,),}# 缓存1小时cache.set(cache_key, product,timeout3600)except Product.DoesNotExist: productNonereturnproduct staticmethod def clear_product_cache(product_idNone): 清理商品缓存ifproduct_id:# 删除单个商品缓存cache.delete(fproduct_detail:{product_id})# 删除商品列表缓存cache.delete(products)# 可以添加更多商品相关的缓存清理3. 视图# views.pyfrom django.httpimportJsonResponse from django.views.decorators.cacheimportcache_page from .services.product_serviceimportProductService cache_page(60*5)# 缓存5分钟def product_list(request):商品列表页 categoryrequest.GET.get(category)productsProductService.get_products(categorycategory)returnJsonResponse({products:products})def product_detail(request, product_id):商品详情页 productProductService.get_product_detail(product_id)ifproduct is None:returnJsonResponse({error:商品不存在},status404)returnJsonResponse(product)# 后台管理更新商品时清理缓存def update_product(request, product_id): 更新商品示例实际需要POST请求和表单验证# ... 更新商品的逻辑 ...# 更新后清理缓存ProductService.clear_product_cache(product_id)returnJsonResponse({message:更新成功})七、高级技巧1. 缓存装饰器# utils/decorators.pyfrom django.core.cacheimportcache from functoolsimportwrapsimporthashlibimportjson def cache_result(timeout300): 缓存函数结果的装饰器 def decorator(func): wraps(func)def wrapper(*args, **kwargs):# 生成唯一的缓存键func_namefunc.__name__ args_strjson.dumps(args,sort_keysTrue)kwargs_strjson.dumps(kwargs,sort_keysTrue)key_strf{func_name}:{args_str}:{kwargs_str}# 如果key太长使用hashiflen(key_str)200: key_hashhashlib.md5(key_str.encode()).hexdigest()cache_keyfcache:{func_name}:{key_hash}else: cache_keyfcache:{key_str}# 尝试从缓存获取resultcache.get(cache_key)ifresult is not None:returnresult# 执行函数resultfunc(*args, **kwargs)# 存入缓存cache.set(cache_key, result,timeouttimeout)returnresultreturnwrapperreturndecorator# 使用示例from utils.decoratorsimportcache_result class UserService: staticmethod cache_result(timeout600)# 缓存10分钟def get_user_stats(user_id):获取用户统计信息耗时操作# 模拟耗时计算importtimetime.sleep(2)return{total_orders:100,total_spent:5000.00,vip_level:3}2. 缓存版本控制def get_with_version(): 缓存版本控制 当数据结构变化时可以通过版本号避免问题# 设置缓存指定版本cache.set(my_key,value,version2)# 获取缓存指定版本value_v1cache.get(my_key,version1)# Nonevalue_v2cache.get(my_key,version2)# value# 删除特定版本cache.delete(my_key,version2)# 递增版本号cache.incr_version(my_key)八、生产环境配置# settings/production.pyimportos CACHES{default:{BACKEND:django_redis.cache.RedisCache,LOCATION:os.getenv(REDIS_URL,redis://127.0.0.1:6379/0),OPTIONS:{CLIENT_CLASS:django_redis.client.DefaultClient,PASSWORD:os.getenv(REDIS_PASSWORD,),SOCKET_TIMEOUT:5,# 5秒超时SOCKET_CONNECT_TIMEOUT:5,# 5秒连接超时CONNECTION_POOL_KWARGS:{max_connections:100,# 连接池大小},COMPRESSOR:django_redis.compressors.zlib.ZlibCompressor,},KEY_PREFIX:myproject_prod,# 生产环境前缀TIMEOUT:60*30,# 默认30分钟}}九、常见问题解决1. 缓存穿透大量查询不存在的数据def get_product_safe(product_id): 防止缓存穿透缓存空值 cache_keyfproduct:{product_id}productcache.get(cache_key)ifproduct is None:# 查询数据库try: productProduct.objects.get(idproduct_id)cache.set(cache_key, product,timeout3600)except Product.DoesNotExist:# 缓存空值短时间过期cache.set(cache_key,NULL,timeout60)productNoneelifproductNULL:productNonereturnproduct2. 缓存雪崩大量缓存同时过期importrandom def set_with_random_ttl(key, value,base_ttl3600): 设置随机过期时间避免大量缓存同时过期# 添加随机抖动±300秒ttlbase_ttl random.randint(-300,300)cache.set(key, value,timeoutttl)returnttl十、总结适合使用缓存的场景频繁读取很少修改的数据如商品分类、城市列表计算结果耗时的数据如统计报表、排行榜会话数据用户登录状态临时数据验证码、短信发送频率限制不适合使用缓存的场景实时性要求高的数据如股票价格频繁修改的数据缓存频繁失效意义不大敏感数据除非做好安全措施简单原则先让功能跑起来再考虑优化缓存不是万能的不要过度使用记得设置合理的过期时间数据更新时及时清理相关缓存这个简明教程涵盖了Django中使用Redis缓存的主要方面从安装配置到实际应用。根据你的项目需求选择合适的方式使用缓存即可。