• 轮播图接口加缓存和定时更新(双写一致性问题以及其解决方案)


    一、轮播图加缓存

    有些知名网站首页被访问的频率很高,假设瞬间 1w个人在访问,首页的轮播图接口会执行1w次,1w次查询轮播图标的sql在执行,轮播图基本不变,首先我们给自己写的轮播图接口加缓存,我们可以用缓存数据库Redis来实现加缓存的需求

    首先罗列一下文字版的逻辑,之后在代码上实现

    1. 当轮播图接口来了请求
    2. 先去缓存看看,如果有缓存,直接返回
    3. 如果没有缓存,则去数据库查询
    4. 然后拿到数据放到Redis中,缓存起来

    通过代码实现加缓存

    python
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.mixins import ListModelMixin
    from luffy_api.utils.common_response import APIResponse
    from .models import Banner
    from .serializer import BannerSerializer
    from django.core.cache import cache
    
    
    class BannerView(GenericViewSet, ListModelMixin):
        queryset = Banner.objects.filter(is_delete=False, is_show=True).order_by('orders')
        serializer_class = BannerSerializer
        """没加缓存的逻辑"""
        # def list(self, request, *args, **kwargs):
        #     res = super().list(request, *args, **kwargs)
        #     return APIResponse(data=res.data, headers={'Access-control-Allow-Origin': '*'})
        """加缓存之后的逻辑"""
        def list(self, request, *args, **kwargs):
            # 查看缓存有没有数据
            banner_list = cache.get('banner_list')
            if banner_list:
                print('走了缓存')
                return APIResponse(data=banner_list)
            else:
                print('走了数据库')
                res = super().list(request, *args, **kwargs)
                cache.set('banner_list', res.data)
                return APIResponse(data=res.data)
    


    Redis数据库也查到了缓存数据的信息

    二、那么到底什么是双写一致性?

    双写一致性指的是当我们更新了数据库的数据之后redis中的数据 也要同步去更新。使用redis读取数据的流程,当用户访问数据的时候,会先从缓存中读取数据,如果命中缓存的话,那么直接把缓存中的数据返回给用户,如果缓存中没有数据的话,先查询数据库把查询到的数据保存到缓存中,然后返回给用户。总结下来就是写入mysql,redis没动,数据不一致存在问题

    三、如何解决双写一致性问题

    1. 修改数据,删除缓存
    2. 修改数据,更新缓存
    3. 定时更新,用celery

    四、使用celery来解决双写一致性问题

    通过截图解释代码的流程

    在celery.py文件里面写如下代码

    python
    from datetime import timedelta
    from celery import Celery
    import os
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev')
    # 提交的异步任务,放在里面
    broker = 'redis://127.0.0.1:6379/1'
    # 执行完的结果,放在这里
    backend = 'redis://127.0.0.1:6379/2'
    # 不要忘了include
    app = Celery('test', broker=broker, backend=backend,
                 include=['celery_task.banner_update_task'])
    
    # 任务的定时配置(celery的配置文件)
    app.conf.timezone = 'Asia/Shanghai'  # 时区
    app.conf.enable_utc = False  # 是否使用UTC
    # 定时任务
    app.conf.beat_schedule = {
        'update_banner': {
            'task': 'celery_task.banner_update_task.update_banner',
            'schedule': timedelta(seconds=3),  # 时间对象
        },
    }
    

    在任务文件里面写如下代码

    python
    from .celery import app
    from home.models import Banner
    from home.serializer import BannerSerializer
    from django.core.cache import cache
    from django.conf import settings
    
    
    @app.task
    def update_banner():
        # 只要这个任务一执行,就更新轮播图的缓存
        banners = Banner.objects.all().filter(is_delete=False, is_show=True).order_by('orders')
        ser = BannerSerializer(instance=banners, many=True)
        for item in ser.data:
            item['image'] = settings.BACKEND_URL + item['image']
    
        cache.set('banner_list', ser.data)  # 会出问题,轮播图地址显示不全
        return True
    

    启动worker

    python
    celery  -A celery_task  worker -l info -P eventlet

    启动beat

    python
    celery -A celery_task beat -l info

    确保过程中不出错,把前后端都重启一遍


    __EOF__

  • 本文作者: The Road of Learning 阿丽米热
  • 本文链接: https://www.cnblogs.com/almira998/p/17208674.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    原生JS实现飞机大战游戏 超详细解析 快来做一个自己玩吧
    生成二维码。且可调颜色
    Uniapp小程序开发-底部tabbar的开发思路
    APP测试中ios和Android的区别是什么~
    IntelliJ IDEA一站式配置【全】(提高开发效率)
    GIT开发学习——fatal: bad revision ‘7450ad67‘
    Self -Attention、Cross-Attention?
    可视化 | (一)数据基础及基本数据可视化方法
    Oracle中全表扫描优化方法
    【接口自动化测试入门】接口测试基础(超详细~)
  • 原文地址:https://www.cnblogs.com/almira998/p/17208674.html