字符编码梳理,celery 执行异步任务,延迟任务,定时任务, django中使用celery,模拟秒杀功能实例,轮播图接口加缓存,双写一致性,首页轮播图定时更新,课程前端页面
字符编码梳理
字符编码:数字计算机中的存储器唯一可以存储的是比特(bit),因此如果要想在计算机上处理信息,就必须把它们按位存储。为了将文本表示为数字形式,我们需要构建一种系统来为每一个字母赋予一个唯一的编码。数字和标点符号也算做文本的一种形式,所以它们也必须拥有自己的编码。
所有由符号所表示的字母和数字(Alphanumeric)都需要编码。具有这种功能的系统被称为字符编码集(Coded Character Set),系统内的每个独立编码称为字符编码(Character Codes)。
ASCII
ASCII码就是一种被广泛使用的字符编码标准,它被称为美国信息交换标准码,从1967年正式公布至今,它一直是计算机产业中最重要的标准。ASCII码是7位编码,它的二进制取值范围为0000000~1111111,对应于十六进制就是00h~7Fh,最多可以表示128个编码。
ASCII的局限性
简单的7位编码只适用于以英语为主的国家,在面对数以万计的中国、日本、韩国的象形文字,以及奇怪的朝鲜文音节等各国语言面前就不够用了。
Unicode
Unicode,统一码,也叫万国码,简称为UCS。现在用的是UCS-2,即2个字节编码.
相对于ASCII的7位编码,目前Unicode采用了16位编码,每一个字符需要2个字节。
UTF-8
虽然Unicode字符集中的码位唯一,但由于计算机存储数据通常是以字节为单位的,而且出于兼容之前的ASCII、大数小段数段、节省存储空间等诸多原因,通常情况下,我们需要一种具体的编码方式来对字符码位进行存储。
以UTF-8为例,其采用了1~6字节的变长编码方式编码Unicode,英文通常使用1字节表示,且与ASCII是兼容的,而中文常用3字节进行表示。UTF-8编码由于较为节约存储空间,因此使用得比较广泛。
celery 执行异步任务,延迟任务,定时任务
elery 执行异步任务,延迟任务
# timedelta做时间计算的
from datetime import datetime,timedelta
eta = datetime.utcnow()+timedelta(seconds=20)
# 异步执行
res = send_sms.delay('188558888','9999')
print(res)
# 5秒后执行这个任务 异步执行
res = send_sms.apply_async(args=['18898555555','8888'],eta=eta)
print(res)
celery 执行定时任务
from celery import Celery
from datetime import datetime,timedelta
from celery.schedules import crontab
# 第一步:在celery的py文件中写入
app.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
app.conf.enable_utc = False
# celery的配置文件#####
# 任务的定时配置
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.秒杀逻辑分析
1 前端秒杀按钮,用户点击---》发送ajax请求到后端
2 视图函数---》提交秒杀任务---》借助于celery,提交到中间件中了
3 当次秒杀的请求,就回去了,携带者任务id号在前端
4 前端开启定时任务,每隔3s钟,带着任务,向后端发送请求,查看是否秒杀成功
5 后端的情况
1 任务还在等待被执行----》返回给前端,前端继续每隔3s发送一次请求
2 任务执行完了,秒杀成功了---》返回给前端,恭喜您秒杀成功--》关闭前端定时器
3 任务执行完了,秒杀失败了---》返回给前端,秒杀失败--》关闭前端定时器
2.视图
# 秒杀逻辑
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='还在秒杀中')
else:
return APIResponse()
3.任务 order_task.py
import random
import time
@app.task
def sckill_task(good_id):
# 生成一个订单,减库存,都在一个事务中
print("商品%s:秒杀开始" % good_id)
time.sleep(random.choice([6,7,9]))
print("商品%s:秒杀结束" % good_id)
return random.choice([True,False])
4.前端Sckill.vue
<template>
<button @click="handleSckill">秒杀</button>
</template>
<script>
import Header from '@/components/Header.vue';
import Banner from '@/components/Banner.vue';
import Footer from '@/components/Footer.vue';
export default {
name: 'Sckill',
data(){
return{
task_id:'',
t:null
}
},
methods:{
handleSckill(){
// 响应状态码是200会走then这一条,状态码不是200会走catch
this.$axios.get(this.$settings.BASE_URL+'/user/sckill/sckill/?id=888').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)
}
})
})
}).catch(res=>{
})
}
}
}
</script>
<style scoped>
</style>
django中使用celery
# 使用步骤:
-1 把写的包,复制到项目目录下
-luffy_api
-celery_task #celery的包路径
-luffy_api #源代码路径
-2 在使用提交异步任务的位置,导入使用即可
-视图函数中使用,导入任务
-任务.delay() # 提交任务
-3 启动worker,如果有定时任务,启动beat
-4 等待任务被worker执行
-5 在视图函数中,查询任务执行的结果
# 补充:如果在公司中,只是做定时任务,还有一个更简单的框架
APSchedule:https://blog.csdn.net/qq_41341757/article/details/118759836
轮播图接口加缓存
# 1 网站首页被访问的频率很高,瞬间 1w个人在访问,首页的轮播图接口会执行1w次,1w次查询轮播图标的sql在执行,轮播图基本不变
# 2 想一种方式,让这1w个访问,效率更高一些,不查数据库了,直接走缓存--》redis--》效率高
# 3 现在的逻辑变成了
1 轮播图接口请求来了,先去缓存中看,如果有,直接返回
2 如果没有,查数据库,然后把轮播图数据,放到redis中,缓存起来
# 加入缓存的轮播图接口
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)
# 把序列化后的数据存到缓存中,redis中
cache.set('banner_list',res.data)
return APIResponse(data=res.data)
双写一致性与首页轮播图定时更新
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
# 加入缓存后,缓存中有数据,先去缓存拿,但是如果mysql中数据变了,缓存不会自动变化,出现数据不一致的问题
mysql 和 缓存数据库 数据不一致
# 双写一致性
写入mysql,redis没动,数据不一致存在问题
#如何解决
1 修改数据,删除缓存
2 修改数据,更新缓存
3 定时更新缓存 ---》实时性差
'update_banner': {
'task': 'celery_task.home_task.update_banner',
'schedule': timedelta(seconds=3), # 时间对象
},
课程前端页面
# 免费课,实战课,轻课
-不要钱的,免费的
-实战课:python面向对象 39.9
-线下课程完整版的视频 19999
# 课程列表页数据
1 新建3个页面组件
FreeCourserView
ActualCourserView
LightCourseView
2 配置路由
{
path: '/free-course',
name: 'free',
component: FreeCourserView
},
{
path: '/actual-course',
name: 'actual-course',
component: ActualCourserView
},
{
path: '/light-course',
name: 'light-course',
component: LightCourseView
},
<summary>ActualCourserView.py</summary>
<template>
- 课程分类:
- 全部
- Python
- Linux运维
- Python进阶
- 开发工具
- Go语言
- 机器学习
- 技术生涯
<div class="ordering">
<ul>
<li class="title">筛 选:</li>
<li class="default this">默认</li>
<li class="hot">人气</li>
<li class="price">价格</li>
</ul>
<p class="condition-result">共21个课程</p>
</div>
</div>
<!-- 课程列表 -->
<div class="course-list">
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
</div>
</div>
<Footer></Footer>
<summary>FreeCourserView</summary>
<template>
- 课程分类:
- 全部
- Python
- Linux运维
- Python进阶
- 开发工具
- Go语言
- 机器学习
- 技术生涯
<div class="ordering">
<ul>
<li class="title">筛 选:</li>
<li class="default this">默认</li>
<li class="hot">人气</li>
<li class="price">价格</li>
</ul>
<p class="condition-result">共21个课程</p>
</div>
</div>
<!-- 课程列表 -->
<div class="course-list">
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
<div class="course-item">
<div class="course-image">
<img src="@/assets/img/course-cover.jpeg" alt="">
</div>
<div class="course-info">
<h3>Python开发21天入门 <span><img src="@/assets/img/avatar1.svg" alt="">100人已加入学习</span></h3>
<p class="teather-info">Alex 金角大王 老男孩Python教学总监 <span>共154课时/更新完成</span></p>
<ul class="lesson-list">
<li><span class="lesson-title">01 | 第1节:初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span> <span class="free">免费</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码</span></li>
<li><span class="lesson-title">01 | 第1节:初识编码初识编码</span></li>
</ul>
<div class="pay-box">
<span class="discount-type">限时免费</span>
<span class="discount-price">¥0.00元</span>
<span class="original-price">原价:9.00元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
</div>
</div>
<Footer></Footer>
LightCourseView
index.js
import Vue from 'vue' import VueRouter from 'vue-router' import HomeView from '../views/HomeView.vue' import Sckill from "@/views/Sckill"; import FreeCourserView from "@/views/FreeCourserView"; import ActualCourserView from "@/views/ActualCourserView"; import LightCourserView from "@/views/LightCourserView";Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/sckill',
name: 'sckill',
component: Sckill
},
{
path: '/free-course',
name: 'free',
component: FreeCourserView
},
{
path: '/actual-course',
name: 'actual-course',
component: ActualCourserView
},
{
path: '/light-course',
name: 'light-course',
component: LightCourserView
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router