Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python后端技术栈(八)--系统设计

Python后端技术栈(八)--系统设计

作者头像
小闫同学啊
发布于 2019-07-18 08:24:41
发布于 2019-07-18 08:24:41
1.6K00
代码可运行
举报
文章被收录于专栏:小闫笔记小闫笔记
运行总次数:0
代码可运行

正文共:3342 字 1 图 预计阅读时间:10 分钟

每日分享

Breathe. Take care. Stand still for a minute. What you are looking for might just be looking for you too.

呼吸。 放轻松。 静止一会儿。 您正在寻找的也可能只是在寻找您。

小闫语录:

充实自己,提升自己,照顾好自己,以全盛的姿态去迎接即将到来的、你要寻找的东西。它不会缺席,迟到只是浪费时间在寻找你的路上。不要放弃,更不要为了寻找变的狼狈。

1.8系统设计

上篇文章传送门『我是个链接

上篇文章对 Python web 框架中的一些经典问题做了总结,比如 WSGI、web 框架、网络安全问题、RESTful 以及 RESTful API

本篇文章将开始系统设计的相关内容,开始咯~

1.8.1 系统设计相关内容

1.什么是系统设计

2.系统设计需要掌握哪些知识

3.如何设计以及如何实现一个后端系统服务的设计

1.8.1.1 什么是系统设计 System Design

系统设计是一个定义系统架构、模块、接口和数据满足特定需求的过程。比如设计一个短网址服务、评论服务、Feed流系统(微博、知乎)、抢红包系统。这些系统设计是最近几年才开始流行起来的,因为现在很多的公司开始采用了微服务架构,在微服务架构之下很多系统被按照业务拆分,需要单独设计一个系统服务。

举个例子,比如短网址服务。一开始是由于 Twitter 只能发 140 个字,很多时候贴一个网址就快占满了,为了解决这个问题,诞生了短网址服务。简单的说就是根据一个长地址生成一个短地址,现在很多网站,比如头条、微博、知乎,大家都能见到这种类似形式的短网址。 在一个公司中会有很多不同的部门,不同的业务,不可能为每一个业务都开发一套。这个时候,公司里可以提供一个供所有业务使用的短网址服务。所有有需要的业务都可以向短网址服务请求接口,获取一个短网址。这就是短网址服务诞生的场景。

1.8.1.2 系统设计的难点

系统设计是中高级工程师必经之路。需要具备相关领域、算法的经验,有一定的架构设计能力。还需要熟悉后端的技术组件,比如消息队列、缓存、数据库和各种 web 框架。我们需要掌握它们的使用场景以及底层原理。比如什么时候去使用缓存?数据同步的问题如何去解决?业务的选型(关系型数据库还是非关系型)?另外一点就是具备文档撰写、流程图绘制、架构设计、编码实现等综合能力。

1.8.1.3 系统设计的要素

系统设计有三大要素

1.适用场景和限制条件;

2.数据存储设计;

3.算法模块设计。

1.8.1.4 要素之一:场景和限制

1.这个系统是在什么地方使用的?比如短网址系统提供给站内各种服务生成短网址。

2.限制条件:用户估计有多少?至少要能支撑多少用户(服务)?

3.估算并发 qps:峰值 qps 是多少?平均 qps 是多少?

qps :每秒的查询请求量

1.8.1.5 要素之二:数据存储设计

数据库的选型:

1.按需求设计数据表,需要哪些字段,使用什么类型?数据增长的规模等。

2.数据库选型:是否需要持久化?使用关系型还是 NoSQL

3.如何优化?如何设计索引?是否可以使用缓存?

1.8.1.6 要素之三:算法模块设计

算法解决问题的核心。程序 = 算法 + 数据结构系统 = 服务 + 存储

1.需要哪些接口?接口如何设计?

2.使用什么算法或者模型?

3.不同实现方式之间的优劣对比,如何取舍?

1.8.1.7 延伸问题

1.用户多了,qps 高了如何处理?

2.数据库存储多了,不够存了如何处理?

3.故障如何处理?单点失败、多点失败、雪崩等问题

1.8.2 系统设计案例-短网址系统设计与实现

1.8.2.1 如何设计与实现一个短网址系统

我们需要考虑下面的几个问题:

1.什么是短网址系统?包含哪些功能(接口)?

2.短网址系统的存储设计?需要存储哪些字段?

3.如何设计算法生成短网址?

1.8.2.2 什么是短网址系统

TinyURL Service,也就是把一个长网址转成短网址的服务。比如 https://bitly.com/(这个网站可以将长网址变成短网址)。转换之后网址的后缀不超过 7 位(字符或者数字)。

1.8.2.3 场景和限制

使用场景:提供短网址服务为公司各业务服务

功能:一个长网址转成短网址并存储;根据短网址还原长 url。

要求:短网址的后缀不超过 7 位(大小写字母和数字)

预估峰值插入请求数量级:数百

查询请求数量级:数千

1.8.2.4 数据存储设计

根据上面的需求,我们使用 MySQL 就可以满足。接下来再思考一下需要的字段有哪些?id 、生成之后的短网址、长网址和生成时间 4 个字段即可。如下:

id

token

url

created_at

自增长编号

短网址生成的 token,不存储整个短网址,因为希望前面的主机名可以随意的替换。此字段建立索引

原网址

创建时间

1.8.2.5 算法实现设计

我们需要考虑短网址生成算法有哪些,然后对比它们的优缺点。

1.首先我们需要提供两个 API 接口。一个是 long2short_url,一个是 short2long_url

我们既要将长网址生成短网址,又要还原查询到跳转网址。

2.常用算法: hash 算法截取;自增序列算法

3.对比多种算法,我们采取自增序列算法实现

短网址生成算法:

这个问题很抽象,我们可以先进行转化一下。也就是每一个长网址从下面的字符集中生成一个不超过 7 位长度的短网址的 token:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

再简单点就是 token 里面的每一个字符都来自上面的字符集。

1.md5 摘要算法是否可以呢?毕竟它可以将任意长度的字节,生成一个定长的字符。此算法多用在我们下载文件的时候,会使用 md5 校验值检查文件是不是被修改了。

利用下面的代码实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import hashlib
hashlib.md5(url.encode()).hexdigest()

大家实验过之后应该会发现它是一个 32 位定长的字符串。但是我们需要 7 位啊?有人会想我们可以截断,比如取前面7个值或者后面7个字符等方式。虽然可以实现,但是会有一定概率的冲突,一旦有冲突,我们在插入的时候还需要去数据库检查一下,这样在高并发的情况下是非常不友好的。

2.如果我们把每一个自增长的 id 生成一个不重复的短网址的 token 呢?想法是不是很美好。我们先来看一下字符集的特点。一共有 62 个字符( 26 个小写英文,26 个大写英文外加 10 个数字,也就是字符集的长度总和为 62),我们需要生成的 token 最长为 7 位,每一位上面都有 62 种可能性,也就是 62 的 7 次幂,是多大呢?万亿级,足够使用了,nice ~。

如果你仔细观察给出的 CHARS 字符集,你会发现它是一个类似于 62 位进制的数字。如果还是不好理解,我们一步一步来,大家都知道二进制的可选项是 0,1 对吧?十六进制是 0 - 9 加 a - f 。而我们此处的 62 进制可选项就是字符集中字符了,此处当然不是严格的 62 进制这样的数字,而是字符集中 0 到 61 位上的每一个字符都与之对应。

简单的说就是根据自增 id 来给每一个长网址生成一个 62 进制的短网址。下面又有问题了,那就是怎么将 10 进制的 id 转换成 62 进制的短网址呢?

先看一个简单的例子,怎么将 10 进制转化成 2 进制。口诀就是不断取余,倒叙输出。Python 中 bin 这个函数可以进行转化,但是我们不用,我们傲娇,我们要自己用代码实现一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def mybin(num): # 10进制 -> 2进制
    if num == 0:
        return 0
    res = []
    while num:
        # 如果10进制要转化成62进制,将下面的2改为62即可
        num, rem = divmod(num, 2)
        res.append(str(rem))
    return ''.join(reversed(res))

里面涉及到一个函数 divmod,我们先来看一下它的简介,然后再举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
In [1]: divmod?
Signature: divmod(x, y, /)
Docstring: Return the tuple (x//y, x%y).  Invariant: div*y + mod == x.
Type:      builtin_function_or_method

In [2]: divmod(10, 2)
Out[2]: (5, 0)

我们可以看到传了两个数之后,返回一个元祖,第一个是取整数,第二个是取余数。

然后编写一段代码,实现 10 进制数字转化为上述字符集 62 进制字符串:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

def encode(num):
    if num == 0:
        return CHARS[0]
    res = []
    while num:
        num, rem = divmod(num, len(CHARS))
        res.append(CHARS[rem])
    return ''.join(reversed(res))

我们将上面的算法称为 递增序列算法,通过这个算法生成短网址。但是还有一个问题,就是数据库只有在插入的时候才有自增 id 。因此我们需要有一个全局的计数器,用来生成自增的 id。计数器可以使用 Redis 的 incr 实现。

下面回顾一下流程

一个请求过来之后,我们先去 Redis 中拿到 incr 的值,然后将值转化成 62 进制串,最后将其保存到 MySQL 中就可以了。

下面我们使用 flask 实现一个短网址服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import os

from flask import Flask, jsonify, render_template, request
from flask_mysqldb import MySQL
from flask.ext.redis import FlaskRedis

app = Flask(__name__)
app.config['MYSQL_USER'] = 'root'
# 此处填写自己电脑的密码
app.config['MYSQL_PASSWORD'] = os.getenv('MYSQL_PASS')
app.config['MYSQL_DB'] = 'test'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'

mysql = MySQL(app)
redis_store = FlaskRedis(app)

CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

def encode(num):
    if num == 0:
        return CHARS[0]
    res = []
    while num:
        num, rem = divmod(num, len(CHARS))
        res.append(CHARS[rem])
    return ''.join(reversed(res))

@app.route('/shorten', methods=['POST'])
def shorten_url():
    long_url = request.json['url']
    index = int(redis_store.incr('SHORT_CNT'))
    token = encode(index)
    sql = "INSERT INTO short_url(token, url) VALUES(%s, %s)"
    cur = mysql.connection.cursor()
    cur.execute(sql, (token, long_url))
    mysql.connection.commit()
    shourt_url = 'https://short.com/' + token
    return jsonify(url=short_url)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True)

数据库所需表:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE short_url (
    id bigint unsigned NOT NULL AUTO_INCREMENT,
    token varchar(10),
    url varchar(2048),
    created_at timestamp NOT  NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_token` (`token`)
);

前端页面此处不提供,只提供后端代码。

结束语

截止到现在,这一系列的笔记就完成了!当然,这八篇文章不可能面面俱到,只能将一些重点提到,树的枝干有了之后,就看大家去如何丰富了,希望这些笔记对大家有所帮助。每天其实最开心的就是晚上看到后台增长的粉丝数。虽然我只是一个很小的公众号,内容也不是多么精彩,但是我愿意不断的进步,也希望大家随着我一起进步。完全的免费,只有你们的认可才是我坚持下去的动力,所以喜欢就分享出去,让更多的人看到吧。

优质文章推荐:

redis操作命令总结

MySQL相关操作

SQL查询语句

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

DRF框架

Django相关知识点回顾

python技术面试题-腾讯

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈技术精选 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
短链系统设计-存储设计
scalability 要求多高?存储和 qps 都不高,单机都能搞定。sql+1
JavaEdge
2022/09/14
5990
短链系统设计-存储设计
短网址系统设计
短网址系统负责将某个长网址缩短为一个很短的网址,用户通过访问这个短网址可以重定向到原本的长网址。
大忽悠爱学习
2023/11/02
5420
短网址系统设计
短链系统设计-用户自定义短链
实现一个顾客短网址,使得顾客能创立他们自己的短网址。即你需要在前文基础上再实现一个 createCustom。
JavaEdge
2022/09/14
2.3K0
短链系统设计-用户自定义短链
聊聊base62与tinyURL
base64大家肯定是很熟悉了,那base62是什么东东,它常被用来做短url的映射。
code4it
2018/09/17
1.9K0
高性能短链设计
今天,我们来谈谈如何设计一个高性能短链系统,短链系统设计看起来很简单,但每个点都能展开很多知识点,也是在面试中非常适合考察侯选人的一道设计题,本文将会结合我们生产上稳定运行两年之久的高性能短链系统给大家简单介绍下设计这套系统所涉及的一些思路,希望对大家能有一些帮助。
范蠡
2020/03/18
3.1K0
如何设计一个短链接系统
短链接是一种将长URL地址转换为较短、易于记忆的链接的技术。它通过使用特定的算法或服务将长链接压缩成更短的形式,以便在限制字符长度或需要更简洁的场景下使用。
柯柏技术笔记
2024/01/10
8710
如何设计一个短链接系统
面试的系统设计题,给我整懵了。。。
微博或者短信都有单条发送字数的限制,如果需要分享一个长网址,很容易越出限制,短链服务可以将长网址变成短网址,方便传播。
JavaSouth南哥
2024/12/05
1600
面试的系统设计题,给我整懵了。。。
短链接技术解析:链接的简化之道
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/12/23
1.3K0
如何设计短网址服务
本文虽然是作者几年前的文章,但并不过时!文中介绍了如何设计短网址服务,简洁地指出了该服务要注意的问题和解决方案。下面是正文:
HelloGitHub
2021/05/14
1.2K0
如何设计短网址服务
手把手教你造轮子:这个价值100万的短网址微服务,我送给你
网上已经有产品,用着还不错。可是,作为程序员,从零开始造轮子,开发一个属于自己的短网址服务器,这想法amazing!
程序员小助手
2020/04/08
5960
短链接原理及其算法实现
短网址在目前来说是一个非常流行的东西,提供短网址服务的网站也是相当多的,短网址在微博上应用的比较广泛 ,因为微博对于url的长度有一个限制,所以将一个很长的网址转换成一个很短的网址,是一个非常棒的想法,其好处有很多,比如字符少,美观,便于发布和传播等。
OECOM
2020/07/01
5.3K0
【转】系统设计-第08章:短网址设计
在这一章中,我们将解决一个有趣而经典的系统设计面试问题:设计一个像tinyurl一样的URL缩短服务。
保持热爱奔赴山海
2024/10/29
2000
字节二面:100Wqps短链系统,如何设计?
这段时间,在整理知识星球中面试专栏时看到这么一个字节跳动的二面真题:100Wqps短链系统,怎么设计?
码猿技术专栏
2023/05/01
4.5K1
字节二面:100Wqps短链系统,如何设计?
设计一个短链接系统
我们可以讲十进制的数字id,转换为一个62进制的数,例如20201122就可以转换为WvOi。
用户3467126
2020/12/01
1.5K0
设计一个短链接系统
如何设计一个微博系统?- 4招教你搞定系统设计
系统设计面试中,经常会被问到如何设计微信、如何设计微博、如何设计百度……我们怎么能在如此短的时间内设计出来一个由成千上万的码农、PM,经年累月地迭代出来的如此优秀的产品?如果面试者这么优秀,那还面试啥?百度、谷歌也不可能只是一个搜索框而已,底下的东西复杂去了。
码老思
2023/10/19
6120
如何设计一个微博系统?- 4招教你搞定系统设计
Serverless-实现一个短网址服务(一)
将一个长url生成一个短链接是很常见的需求,本文尝试通过serverless的方式来提供这个功能,主要有两部分内容:
Thor
2020/05/23
1.3K0
如何实现一个短链接服务 | 短链接生成原理
短链接,通俗来说,就是将长的URL网址,通过程序计算等方式,转换为简短的网址字符串。
梦溪
2021/08/09
19.5K3
短网址系统
在微博里发布一条带网址的信息,微博会把里面的网址转化成一个更短的网址。只要访问这个短网址,就相当于访问原始的网址。
Michael阿明
2021/02/20
4.1K0
短网址系统
短网址(short URL)系统的原理及其实现
作者: 小猿大圣 https://segmentfault.com/a/1190000012088345 背景 提供一个短址服务。 你有没有发现,我们的任务中出现长 URL 就会比较麻烦?
前端教程
2018/03/05
5.4K0
短网址(short URL)系统的原理及其实现
PHP网址缩短算法代码(修复PHP7.0问题)
每个网址用6个字符代替,(32^6) 最多可以拥有1,073,741,824个短网址。当然,你还可以记录更详细的信息,如访问记录,创建时间等。如果真不够用了,还可以删掉很久不用的。
墨渊
2018/05/09
3.3K5
相关推荐
短链系统设计-存储设计
更多 >
LV.1
北京博奥瑞科技有限公司全栈开发工程师
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验