首页 > 其他分享 >接口缓存、定时更新、异步发送短信

接口缓存、定时更新、异步发送短信

时间:2023-07-04 22:34:41浏览次数:39  
标签:异步 缓存 res task celery code 定时 data

目录

一、接口缓存

# 所有接口都可以改造,尤其是查询所有的这种接口,如果加入缓存,会极大的提高查询速度

# 首页轮播图接口:获取轮播图数据,加缓存--->咱们只是以它为例

# 增加接口缓存
from django.core.cache import cache
class BannerView(GenericViewSet, ListModelMixin):
    queryset = Banner.objects.all().filter(is_delete=False, is_show=True).order_by('orders')[:settings.BANNER_COUNT]
    serializer_class = BannerSerializer

    def list(self, request, *args, **kwargs):
        '''
          1 先去缓存中查一下有没有数据
          2 如果有,直接返回,不走父类的list了(list在走数据库)
          3 如果没有,走父类list,查询数据库
          4 把返回的数据,放到缓存中
        '''

        data = cache.get('home_banner_list')
        if not data:  # 缓存中没有
            print('走了数据库')
            res = super().list(request, *args, **kwargs)  # 查询数据库
            # 返回的数据,放到缓存中
            data = res.data.get('data')  # {code:100,msg:成功,data:[{},{}]}
            cache.set('home_banner_list', data)
        return APIResponse(data=data)


    
# 公司里可能会这么写
	-写一个查询所有带缓存的基类
    -写个装饰器,只要一配置,就自动带缓存
    
    
# 双写一致性问题:缓存数据和数据库数据不一致了
	-写入数据库,删除缓存
    -写入数据库,更新缓存
    -定时更新缓存

二、双写一致性之定时更新

# 一旦加入缓存,就会出现数据不一致的请请求
# 双写一致性问题
	-1 改数据,删缓存
    -2 改数据,改缓存
    -3 定时更新 --- 接口的数据对于实时性要求不高
    
    
# 首页轮播图存在双写一致性问题这个问题
	-第一种方法,以现在的技术水平,做不到 :改数据删缓存(--后期学习,通过信号机制改动)
	-能选择的就是定时更新
    	-轮播图接口--->实时性要求没有那么高
             

celery的定时任务

定时更新轮播图任务:
    1.查询数据库,拿到所有轮播图数据
    2.序列化后,放到缓存中
启动worker、beta两条命令

代码

celery_task/home_task.py

from home.models import Banner
from django.conf import settings
from home.serializer import BannerSerializer
from django.core.cache import cache


@app.task
def update_banner():
    # 1.查询数据库,拿到所有轮播图数据
    banner_list = Banner.objects.filter(is_delete=False, is_show=True).order_by('orders')[:settings.BANNER_COUNT]
    # 2.序列化后
    ser = BannerSerializer(instance=banner_list, many=True)
    # 前端显示缓存中的路径格式是:/media/banner/banner1.png"
    # 如果在视图类中,做序列化,因为视图类中有request对象,所以像图片这种,会自动加前面地址
    # 在这里没有request对象,需要手动拼
    for item in ser.data:  # [{}, {}, {}]
        item['image'] = settings.BACKEND_URL + item['image']
    # 3.放到缓存中
    cache.set('home_banner_list', ser.data)
    return True

celery_task/celery.py

# 定时配置
from datetime import timedelta

app.conf.beat_schedule = {
    'update_banner': {
        'task': 'celery_task.home_task.update_banner',  # 任务关联的函数
        'schedule': timedelta(seconds=5),  # 时间间隔是由公司来定制的可以,间隔一天,或间隔七天
        'args': (),
    },
}

启动worker、beta

(luffy) E:\python project\luffy_api>celery -A celery worker -l info -P eventlet
(luffy) E:\python project\luffy_api>celery -A celery_task beat -l info

三、异步发送短信

步骤

1.在celery_task中写发送短信的任务
2.需要导入短信模块,要记得导入django配置
3.在视图函数中提交异步任务delay(参数)

视图函数user/views.py

	@action(methods=['GET'], detail=False)
    # 发送短信接口
    def send_sms(self, request, *args, **kwargs):
        # 前端需要把要发送的手机号传入 在地址栏中
        mobile = request.query_params.get('mobile', None)
        # 判断手机号是否合法
        if not re.match(r'^1[3-9][0-9]{9}$', mobile):
            raise APIException('手机号不合法')

        code = get_code()  # 把code存起来,放到缓存中,目前在内存,后期换别的
        cache.set('send_sms_code_%s' % mobile, code)
        # 想要从缓存中取
        # cache.get('send_sms_code_%s' % mobile)
        if mobile:
            # 手机号存在,开启线程(target是线程执行任务),异步发送信息
            # thread = Thread(target=send_sms_by_mobile, args=[mobile, code])
            # thread.start()

            # 使用celery异步发送短信
            res = send_sms_task.delay(mobile, code)
            print(res)  # res是id号,要做个任务表记录下id号
            return APIResponse(msg='短信已发送')
        raise APIException('手机号没有携带')

任务celery_task/user_task.py

from .celery import app
from libs.send_tx_sms import send_sms_by_mobile


@app.task
def send_sms_task(mobile, code):
    res = send_sms_by_mobile(mobile, code)
    if res:
        return '%s的短信发送成功' % mobile
    else:
        return '%s的短信发送失败' % mobile

四、异步秒杀逻辑前后端

4.1 前端 Sckill.vue

<template>
    <div class="skill">
        <el-col :span="24">
            <div class="grid-content bg-purple"><h2>go语言从入门到放弃</h2></div>
        </el-col>
        <el-button type="danger" @click="handleSkill">秒杀</el-button>
    </div>
</template>

<script>
export default {
    name: "Skill",
    data() {
        return {
            task_id: '',
            t: null,
        }
    },
    methods: {
        handleSkill() {
            this.$axios.post(`${this.$settings.BASE_URL}`, {
                name: "性感帽子",  // 向后端发送商品信息跟用户信息
            }).then(res => {
                    if (res.data.code === 100) {
                        alert('您正在排队')
                        // 加载图标
                        const loading = this.$loading({
                            lock: true,
                            text: 'Loading',
                            spinner: 'el-icon-loading',
                            background: 'rgba(0, 0, 0, 0.7)'
                        });
                        setTimeout(() => {
                            loading.close();
                        }, 2000);
                        // 获取id号
                        this.task_id = res.data.task_id

                        // 起定时任务
                        this.t = setInterval(() => {
                            this.$axios.get(`${this.$settings.BASE_URL}user/skill/?task_id=${this.task_id}`).then(res => {
                                // 100是成功,102是失败
                                if (res.data.code === 100 || res.data.code === 101) {
                                    this.$message(res.data.msg)
                                    // 销毁定时器
                                    clearInterval(this.t)
                                    this.t = null
                                } else {
                                    console.log('过会再查')
                                }
                            })
                        }, 3000)
                    }
                }
            )
        }
    },
}
</script>

<style scoped>
.bg-purple {
    background: #d3dce6;
}

.grid-content {
    border-radius: 4px;
    min-height: 36px;
}
</style>

4.2 后端

视图类

from celery_task.user_task import skill_goods
from celery_task.celery import app
from celery.result import AsyncResult


class Skill(APIView):
    def post(self, request, *args, **kwargs):
        name = request.data.get('name')
        # 提交秒杀异步任务
        res = skill_goods.delay(name)
        return APIResponse(task_id=str(res))

    def get(self, request, *args, **kwargs):
        task_id = request.query_params.get('task_id')
        asy = AsyncResult(id=task_id, app=app)
        if asy.successful():  # 正常执行完成
            result = asy.get()  # 任务返回的结果
            if result:
                return APIResponse(code=100, msg=('秒杀成功'))
            else:
                return APIResponse(code=101, msg=('秒杀失败'))
        elif asy.status == 'STARTED':
            print('任务已经开始被执行')
            return APIResponse(code=103, msg='还在排队')
        else:
            return APIResponse(code=102, msg='没成功')

路由

urlpatterns = [
    path('sckill/', SckillView.as_view()),
]

任务:celery_task/user_task.py

@app.task
def skill_goods(name):
    # 逻辑是:开启事务 ---> 扣减内存 ---> 生成订单
    import time
    time.sleep(6)
    res = random.choice([100, 102])
    if res == 100:
        print('%s被秒杀成功了' % name)
        return True
    else:
        print('%s被秒杀失败了' % name)
        return False
    
# 在celery_task的路径下,启动worker
celery -A celery_task worker -l info -P eventlet

标签:异步,缓存,res,task,celery,code,定时,data
From: https://www.cnblogs.com/zjyao/p/17527227.html

相关文章

  • 如何保持缓存和数据库中的数据一致
    背景缓存是软件开发中一个非常有用的概念,数据库缓存更是在项目中必然会遇到的场景。而缓存一致性的保证,更是在面试中被反复问到,这里进行一下总结,针对不同的要求,选择恰到好处的一致性方案。缓存是什么存储的速度是有区别的。缓存就是把低速存储的结果,临时保存在高速存储的技术。......
  • 012双写一致性之定时更新,异步发送短信,异步秒杀逻辑前后端,课程页面前端,课程相关表分析,
    0双写一致性之定时更新#一旦加入缓存,就会出现数据不一致的请请求#双写一致性问题 -1改数据,删缓存-2改数据,改缓存-3定时更新#首页轮播图存在双写一致性问题这个问题 -以现在的技术水平(信号),做不到:改数据删缓存 -能选择的就是定时更新 -轮播......
  • 基于Redis分布式缓存
    1.安装包使用Redis分布式缓存需要安装Redis的支持包,可以通过nuget命令安装,如下:install-packageMicrosoft.Extensions.Caching.StackExchangeRedis 2.在Program.cs文件中注册builder.Services.AddStackExchangeRedisCache(option=>{option.Configuration......
  • Vue内置缓存组件keep-alive
    <el-tab-panelabel="周边配套":disabled=!gardenIdname="five"><keep-alive><Surrour:gardenId="gardenId"v-if="activeName==='five'"/></keep-alive>......
  • webapi中用Quartz(定时任务)的步骤
         文件---新建---项目---ASP.NETWEB应用程序---程序命名---webapiNuget---Quartz(/v2.5)创建要在定时任务中执行的工作内容publicclassRJJob:Ijob创建调度任务(确定执行时间)Global.asax中,加入启动代码:JobScheduler.Start();......
  • 定时发布
    文章发布——异步调用——>文章审核问题:不管文章的发布时间是什么时间段都会立马进行审核,然后生成app端相关的数据此刻:立即发布文章未来时间:按时发布文章 文章发布——》延迟任务服务《——文章审核  ......
  • 达梦定时备份归档及清除
    1概述在实际生产环境中,用户需要数据库能自动完成归档日志备份及归档备份日志的自动清理。2开启归档alterdatabasemount;alterdatabaseaddarchivelog'dest=/dmdata/arch,TYPE=local,FILE_SIZE=1024,SPACE_LIMIT=40000';alterdatabasearchivelog;alterdatabaseopen;3......
  • Flask插件---flask-caching (缓存)
    Flask插件---flask-caching(缓存)安装pipinstallflask-caching加载配置插件在exts.py文件中配置#exts.py:插件管理#扩展的第三方插件#1.导入第三方插件fromflask_sqlalchemyimportSQLAlchemyfromflask_migrateimportMigratefromflask_cachingimportC......
  • Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、防盗链、SSL、性能优化
    Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、防盗链、SSL、性能优化...架构营 2023-07-0307:10 发表于上海收录于合集#nginx2个#架构172个#web2个引言一、性能怪兽-Nginx概念深入浅出二、Nginx环境搭建三、Nginx反向代理-负载均衡......
  • 【HZERO】定时任务
    ......