celery

1.celery介绍

celery能用来做什么:
1.异步任务
2.定时任务
3.延迟任务

1.1 理解celery的运行原理

1.可以不依赖任何服务器 通过自身命令 启动服务

2.celery服务为其他项目服务提供异步解决任务需求
注:会有两个服务同时运行 一个是项目服务 一个是celery服务 项目服务将需要异步处理的任务交给celery服务 celery就会在需要时异步完成项目的需求
项目服务正常服务 和selery服务互不打扰 当 项目服务需要异步操作时 selery服务会完成异步操作

1.2 celery架构(Broker、backend都用redis)

1.任务中间件 Broker(中间件)其他服务提交的异步任务 放在队列里
需要借助第三方: redis rabbitmq
2.任务执行单元 worker 真正执行异步任务的进程
celery提供的
3.结果存储 backend 结果存储 函数的返回结果 存到backend种
需要借助于第三方:redis mysql

1.3使用场景

异步执行:解决耗时任务
延迟执行:解决延迟任务
定时执行:解决周期任务 celery 不支持win 通过eventlet支持在win上运行

2.celery安装

# 安装---》安装完成,会有一个可执行文件 celery
pip install celery
celery 不支持win 通过eventlet支持在win上运行
win:pip install eventlet

3.celery包结构

1.project
├── celery_task # celery包
│ ├── __init__.py # 包文件
│ ├── celery.py # celery连接和配置相关文件,且名字必须交celery.py
│ # 所有任务函数
├── add_task.py # 添加任务
└── get_result.py # 获取结果

4.celery执行异步任务(快速使用)

1.新建一个celery_task--包

2.按照包结构创建py文件

3.celery.py

from celery import Celery

broker = 'redis://127.0.0.1:6379/1'
backend = 'redis://127.0.0.1:6379/2' # app = Celery('test', broker=broker, backend=backend, include=['celery_task.user_task', 'celery_task.order_task'])
app = Celery('test', broker=broker, backend=backend, include=['celery_task.order_task', 'celery_task.user_task'])

4.order_task.py 添加任务

from celery_task.celery import app
import time
@app.task
def add(a, b):
print('-----', a + b)
time.sleep(2)
return a + b

5.user_task.py 添加项目任务


import time
from celery_task.celery import app
@app.task
def send_sms_ss(phone,code):
print("给%s发送短信成功,验证码为%s"%(phone,code))
time.sleep(3)
return True

6.lll_task.py 开启一个其他程序 提交项目任务

from celery_task.user_task import send_sms_ss
res = send_sms_ss.delay('123456789','66666') #立即异步执行
print(res) '''
异步:
任务.delay
'''

7.终端 启动worker

celery  -A selery_task worker -l info -P eventlet

8.worker会执行消息中间件的任务 把结果存起来

9.查看执行结果

from main import app
from celery.result import AsyncResult
id = '51611be7-4914-4bd2-992d-749008e9c1a6'
if __name__ == '__main__':
a = AsyncResult(id=id, app=app)
if a.successful(): # 执行完了
result = a.get() #
print(result)
elif a.failed():
print('任务失败')
elif a.status == 'PENDING':
print('任务等待中被执行')
elif a.status == 'RETRY':
print('任务异常后正在重试')
elif a.status == 'STARTED':
print('任务已经开始被执行')

5.celery执行延迟任务

lll_task.py

from datetime import datetime,timedelta
eta = datetime.utcnow()+timedelta(seconds=20)
res=send_sms_ss.apply_async(args=['123456789','66666'],eta=eta) '''
延迟任务:
任务.apply_async(args=[],eta-eta) r
如果没有修改时区需要使用UTC时间
'''

6.celelry定时任务

需要启动beat和worker
beat --- 定时提交任务的进程 -- 配置在app.conf.beat_schedule的任务
worker --- 执行任务的

使用步骤:

#第一步:在celery中的py文件中写入
app.conf.timezone = 'Asia/Shanghai' #时区修改为上海
app.conf.enable_utc = False #是否使用UTC
#任务的定时配置
app.conf.beat_schedule = {
'send_sms': {
'task': 'celery_task.user_task.send_sms',
# 'schedule': timedelta(seconds=3), # 时间对象
# 'schedule': crontab(hour=8, day_of_week=1), # 每周一早八点
'schedule': crontab(hour=9, minute=43), # 每天9点43
'args': ('18888888', '6666'),
},
} #第二步:启动beat
celery -A celery_task beat -l info #第三步:启动worker
celery -A celery_task worker -l info -P eventlet '''
注意:
1.启动命令的执行位置 如果是包结构 一定在包这一层
2.include = ['celery_task.order_task'],路径从包名下开始导入 因为我们在包这层执行的命令
'''

7.django中使用celery

如果在公司制作定时任务 还有一个更简单的框架
参考:https://blog.csdn.net/qq_41341757/article/details/118759836 使用步骤:
1.把咱们写的包复制到项目目录下
-luffy_lzy
-celery_task #包路径
-luffy_lzy #源代码路径 小路飞 2.在使用提交异步任务的位置 导入使用即可
在试图函数中使用 导入任务
任务.delay() #提交任务 3.启动worker 如果有定时任务 启动beat 4.等待任务被worker执行 5.在视图函数中 查询任务执行的结果

7.1秒杀功能

逻辑分析:
1.前端秒杀按钮 用户点击 --- 发送ajax请求
2.视图函数 -- 提交秒杀任务 -- 借助于celery 提交到中间件中
3.当次秒杀的请求 就回去了 携带者任务id号在前端
4.前端开启定时任务 每隔3秒 带着任务 向后端发送请求 查看是否秒杀成功
5.后端的情况
1.任务还在等待被执行 --- 返回给前端 前端继续没隔3s发送一次请求
2.任务执行完了 秒杀成功 ---返回给前端 恭喜秒杀成功 --关闭前端定时器
3.任务执行完了 秒杀失败 ---返回给后端 秒杀失败--关闭前端定时器

7.2视图

#### 秒杀逻辑,CBV
from rest_framework.viewsets import ViewSet from celery_task.order_task import sckill_task
from celery_task.celery import app
from celery.result import AsyncResult class SckillView(ViewSet):
@action(methods=['GET'], detail=False)
def sckill(self, request):
a = request.query_params.get('id')
# 使用异步,提交一个秒杀任务
res = sckill_task.delay(a)
return APIResponse(task_id=res.id) @action(methods=['GET'], detail=False)
def get_result(self, request):
task_id = request.query_params.get('task_id')
a = AsyncResult(id=task_id, app=app)
if a.successful():
result = a.get()
if result:
return APIResponse(msg='秒杀成功')
else:
return APIResponse(code=101, msg='秒杀失败')
elif a.status == 'PENDING':
print('任务等待中被执行')
return APIResponse(code=666, msg='还在秒杀中')

7.3 任务 order_task.py

# 秒杀任务
import random
import time @app.task
def sckill_task(good_id):
# 生成订单,减库存,都要在一个事务中
print("商品%s:秒杀开始" % good_id)
# 这个过程,可能是1,2,3s中的任意一个
time.sleep(random.choice([6, 7, 9]))
print('商品%s秒杀结束' % good_id) return random.choice([True, False])

7.4前端 Sckill.vue

<template>
<div> <button @click="handleSckill">秒杀</button>
</div>
</template> <script>
import Header from '@/components/Header';
import Banner from '@/components/Banner';
import Footer from '@/components/Footer'; export default {
name: 'Sckill',
data() {
return {
task_id: '',
t: null
}
},
methods: {
handleSckill() {
this.$axios.get(this.$settings.BASE_URL + '/user/sckill/sckill/?id=999').then(res => {
this.task_id = res.data.task_id
this.t = setInterval(() => {
this.$axios.get(this.$settings.BASE_URL + '/user/sckill/get_result/?task_id=' + this.task_id).then(res => {
if (res.data.code == 666) {
//如果秒杀任务还没执行,定时任务继续执行
console.log(res.data.msg)
} else {
// 秒杀结束,无论成功失败,这个定时任务都结束
clearInterval(this.t)
this.t = null
this.$message(res.data.msg)
} })
}, 2000)
}).catch(res => { })
}
} }
</script>

7.5 django中使用celery

-1 把咱们写的包,复制到项目目录下
-luffy_api
-celery_task #celery的包路径
celery.py # 一定不要忘了一句话
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev')
-luffy_api #源代码路径 -2 在使用提交异步任务的位置,导入使用即可
-视图函数中使用,导入任务
-任务.delay() # 提交任务 -3 启动worker,如果有定时任务,启动beat -4 等待任务被worker执行 -5 在视图函数中,查询任务执行的结果 # 重点:celery中使用djagno,有时候,任务中会使用django的orm,缓存,表模型。。。。一定要加
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev')

3.轮播图接口加缓存

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

改接口

#加入缓存的轮播图接口
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):
banner_list = cache.get('banner_list')
#查看缓存有没有数据 如果没有再走数据库
if banner_list:
return APIResponse(data=banner_list)
else: #数据库
res = super().list(request, *args, **kwargs)
cache.set('banner_list',res.data)
return APIResponse(data=res.data)
# {code:100,msg;成功,data=[{},{}]}

8.双写一致性

加入缓存后 缓存中有数据 先去缓存拿 但是如果mysql中数据变了 缓存不会自动变化 出现数据不一致问题 	-- mysql和缓存数据库不一致

双写一致性
写入mysql redis没动 数据不一致存在问题 如何解决
1.修改数据 删除缓存
2.修改数据 更新缓存
3.定时更新缓存 --- 实时性差 #定时任务 :celery

9.首页轮播图定时更新

第一步:在celery配置定时任务
app.conf.beat_schedule = {
'update_banner': {
'task': 'celery_task.home_task.update_banner',
'schedule': timedelta(seconds=3), # 时间对象
},
} 第二步:启动worker 启动beat
# update_banner任务的代码
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

celery 使用的更多相关文章

  1. 异步任务队列Celery在Django中的使用

    前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...

  2. celery使用的一些小坑和技巧(非从无到有的过程)

    纯粹是记录一下自己在刚开始使用的时候遇到的一些坑,以及自己是怎样通过配合redis来解决问题的.文章分为三个部分,一是怎样跑起来,并且怎样监控相关的队列和任务:二是遇到的几个坑:三是给一些自己配合re ...

  3. tornado+sqlalchemy+celery,数据库连接消耗在哪里

    随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知.     最近老是发现数据库的连接数如果 ...

  4. celery 框架

    转自:http://www.cnblogs.com/forward-wang/p/5970806.html 生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据 ...

  5. celery使用方法

    1.celery4.0以上不支持windows,用pip安装celery 2.启动redis-server.exe服务 3.编辑运行celery_blog2.py !/usr/bin/python c ...

  6. Celery的实践指南

    http://www.cnblogs.com/ToDoToTry/p/5453149.html Celery的实践指南   Celery的实践指南 celery原理: celery实际上是实现了一个典 ...

  7. Using Celery with Djang

    This document describes the current stable version of Celery (4.0). For development docs, go here. F ...

  8. centos6u3 安装 celery 总结

    耗时大概6小时. 执行 pip install celery 之后, 在 mac 上 celery 可以正常运行, 在 centos 6u3 上报错如下: Traceback (most recent ...

  9. celery 异步任务小记

    这里有一篇写的不错的:http://www.jianshu.com/p/1840035cb510 自己的"格式化"后的内容备忘下: 我们总在说c10k的问题, 也做了不少优化, 然 ...

  10. Celery 框架学习笔记

    在学习Celery之前,我先简单的去了解了一下什么是生产者消费者模式. 生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是 ...

随机推荐

  1. ARC(Automatic Reference Counting)自动引用计数 unowned、weak 使用区别

    自动引用计数 引用类型(类.函数.闭包) 当声明一个变量指向某个引用类型时 当前引用类型的引用计数就会加1 当变量不指向该类型时 引用类型就会 -1 当引用计数为0时  当前引用类型就会被系统回收 i ...

  2. Unity 纯C# 完成 APK从下载到 自安装

    最简单的就是用androidStudio 进行编辑,打个aar 包,在Unity中调用方法,很便捷以下内容均转载Unity论坛,Android API24版本下可用,android API 24以上版 ...

  3. 个人js基础知识及看js高级程序设计查漏 汇总

    1.事件循环机制 js单线程操作. 1>主线程读取js代码 ,此时为同步环境,形成相应的堆和执行栈. 2>主线程遇到异步任务,指给对应的异步进程处理. 3>异步进程处理完毕后,将相应 ...

  4. js模块化 CommonJS和AMD/CMD ES6模块化

    ES6之前已经出现了js模块方案,有CommonJS和AMD规范.commonjs实现同步加载应用于服务器,如nodejs.AMD为异步加载应用于浏览器,如requirejs. ES6在语言层面上模块 ...

  5. 从零搭建php环境-php8-扩展-redis

    一.下载1.https://pecl.php.net/get/redis-5.3.2.tgz下载到本地,文件传输上传到 /usr/local/src/2.wget -P /usr/local/src/ ...

  6. JAVA第六七八次大作业

         21201411-李英涵            前言:这几次的作业较为简单,主要思路就是利用正则表达式来过滤掉不需要的信息.  题量设置较为合理,比之前的多边形好做一些,应该是老师为了捞起来 ...

  7. PHP、Navicat安装

    一.PHPStudy小皮面板:https://public.xp.cn/upgrades/phpStudy_64.zip 下载完成后解压后双击 点击立即安装 安装完成 启动MySQL,Nginx(my ...

  8. 获取指定字符串第n次出现的位置索引

    returnIndex(str,cha,num){ var x=str.indexOf(cha); for(var i=0;i<num;i++){ x=str.indexOf(cha,x+1); ...

  9. Android studio应用

    菜单的使用 public class FirstActivity extends AppCompatActivity { @Override protected void onCreate(Bundl ...

  10. 图论之最小生成树问题(kruskal)

    最近有几位同学催我更新,于是来摸摸鱼,来讲一下最小生成树问题. 所谓最小生成树(MST),就是在一张无向带权图中的一棵经过所有节点,边权和最小的一棵树.在实际生活中,可以运用于城镇之间的修路上. 对于 ...