Flask项目(6)

该博客介绍了如何使用Redis进行统计数据的持久存储,对比了旧有的统计发布文章数量方案与新的方案,并详细讲解了如何利用APScheduler进行定时任务设置,包括date、cron和interval触发器的使用。同时,还涉及到RPC调用的原因、gRPC的基本概念以及protobuf语法,以及如何通过gRPC创建服务器和客户端进行通信。
摘要由CSDN通过智能技术生成

学习目标

1.能够封装头条项目统计数据存储类
	类函数
	incr
	get

2.能够知道需要修正redis存储的统计数据原因
	mysql 成功
	redis 失败
	
3.能够知道APScheduler的特点
	1.动态添加
	2.不依赖linux crontab

4.能够使用APScheduler编写定时任务
	1.导入模块
	2.创建执行器
	3.创建调度器
	4.定义定时任务函数
	5.添加定时任务
	6.启动调度器
	7.防止退出的代码

5.能够编写头条项目修正统计数据的定时任务
	1.从数据库中获取统计数据
	# 用户发表文章数量
	# sql: select user_id, count(*) from news_article_basic where status=2 group by user_id;

	2.更新redis数据
		pl = current_app.redis_master.pipeline()
		pl.delete(key)
		zadd(key, count1, user_id1, count2, user_id2)
		pl.zadd(key, *data)
		pl.execute()
	
6.能够知道RPC的作用
	远程调用服务器的方法

7.能够对比HTTP与RPC
	1.http更加通用
		面向产品
	2.RPC效率高,但是不通用
		微服务

8.能够知道RPC的使用方法
	1.定义接口文件 .proto
	2.生成源代码文件
	3.编辑客户端和服务端逻辑代码

9.能够使用protobuf编写接口定义文件
	1.syntax = "proto3";
	2.message Request{
			repeated string name=1;
	}
	 message Response{}
	 	
	3.service Hello{
			rpc say(Request) returns (Response)
	}

10.能够使用grpc提供的工具编译proto文件生成python代码
	python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. hello.proto

11.能够编写grpc服务器程序
	1.导入模块
	2.自定义服务类,继承生成服务类 HelloServicer
		重写服务类方法
	3.创建rpc 服务器 server
		server = grpc.server()
	4.把自定义服务类添加到server中
	5.绑定ip和端口号
	6.启动
	7.防止退出

12.能够编写grpc客户端程序
	1.导入模块
	2.创建通道
	3.创建存根 stub, 需要使用到上面创建的通道
	4.构建请求参数对象
	5.使用stub调用rpc服务类方法
	6.处理结果
13.能够实现头条项目首页推荐接口

1.统计数据使用redis进行持久存储

原来统计数据的设计:在user_basic表中,添加字段进行统计。
	存在的问题:
		1.在高并发的情况下,在统一时刻触发统计的数量是巨大的。
    2.为了数据的准确性,又必须加锁。所以对数据库的性能影响是巨大的。

在redis中,每个命令都是原子性的,既能提供高性能的访问,也能保证数据修改的完整性。

黑马头条项目:
	统计数据最终的选择方案是使用redis进行缓存。

2.旧统计发布文章数量方案

  • 文件:d01_old_statistics.py

  • 关键代码:

  • 发布文章:

    @app.route('/issue_article/<int:user_id>')
    def issue_article(user_id):
        # 发布文章
        # 为了测试方便,从数据库查一条文章数据
        article_obj = Article.query.first()
        content_obj = ArticleContent.query.get(article_obj.id)
        # user_id发布文章
        user_article = Article(
            user_id=user_id,
            channel_id=article_obj.channel_id,
            title=article_obj.title,
            cover=article_obj.cover,
            is_advertising=article_obj.is_advertising,
            ctime=article_obj.ctime,
            status=article_obj.status,
            reviewer_id=article_obj.reviewer_id,
            review_time=article_obj.review_time,
            delete_time=article_obj.delete_time,
            comment_count=article_obj.comment_count,
            allow_comment=article_obj.allow_comment,
            reject_reason=article_obj.reject_reason,
            utime=article_obj.utime
        )
        db.session.add(user_article)
        # 把sql发送到mysql中执行,并没有commit.
        db.session.flush()
        user_content = ArticleContent(
            id=user_article.id,
            content=content_obj.content
        )
        db.session.add(user_content)
        # db.session.commit()
        user = User.query.get(user_id)
        user.article_count = user.article_count + 1
        db.session.add(user)
        db.session.commit()
        # 视图中默认会加上db.session.rollback()
        return '发布成功'
    
  • 获取文章数量

    @app.route('/article_count/<int:user_id>')
    def article_count(user_id):
    		#获取用户发布文章数量
        user = User.query.get(user_id)
        return str(user.article_count)
    

3.新统计发布文章数量方案

  • 用户发布文章redis数据库设计思路分析:

  • 所有用户发布文章数量全部放在一个key中.

  • key: count:user:arts

  • value: 值选择zset类型

    member: 选择user_id
    score:  选择用户发布文章的数量
    
  • 文件:d02_new_statistics.py

  • 获取用户发布文章数量

    # redis命令: zscore key user_id
    count = app.redis_slave.zscore('count:user:arts', user_id)
    
  • 发布文章,用户发布文章数量加1

    # redis命令: zincrby key increment user_id
    app.redis_master.zincrby('count:user:arts', user_id, 1)
    
  • 错误的操作:

    count = app.redis_slave.zscore('count:user:arts', user_id)
    # 此时有可能出现并发
    count += 1
    app.redis_slave.zadd('count:user:arts', count, user_id)
    
  • 备注

    执行zincrby命令,是原子性的,不会出现并发改的情况,只有要么成功要么失败。
    

4.用户发布文章数量统计存储类封装

  • 封装成工具类

  • 文件: d03_user_article_count_tool.py

    class UserArticlesCountStorage(object):
        """ 用户文章数量 """
        key = 'count:user:arts'
    
        @classmethod
        def incr(cls, user_id, increment=1):
    				current_app.redis_master.zincrby(cls.key, user_id, increment)
    
        @classmethod
        def get(cls, 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值