字节青训营

微服务架构

了解微服务架构

  • 优势:

    1. 开发效率高、2. 业务独立设计、3. 自下而上、4. 故障隔离
  • 劣势:

    1. 治理、运维难度高、2. 观测挑战、3. 安全性、4. 分布式系统的问题

核心要素

  • 服务治理

    1. 服务注册、2. 服务发现、3. 负载均衡、4. 扩缩容、5. 流量治理、6. 稳定性治理
  • 可观测性

    1. 日志采集、2. 日志分析、3. 监控打点、4. 监控大盘、5. 异常报警、6. 链路追踪
  • 安全

    1. 身份验证、2. 认证授权、3. 访问令牌、4. 审计、5. 传输加密、5. 黑产攻击

微服务架构原理及特征

基本概念

  • 服务(service)

定时计划

基本的定时任务

  • Windows运行批处理文件

  • Windows任务计划程序(右键我的电脑

  • Linux命令—CronJob

  • 应用程序编码层—单机定时任务(Timer—JavaTicker—GoScheduledExecutorService—线程池技术)

  • 任务调度—Quartz(单任务极致控制、没有负载均衡机制)

  • 分布式定时任务(平台化管理、分布式部署、支持海量数据)

分布式定时任务

  • 定时任务是指系统为了自动完成特定任务,实时、延时、周期性完成任务调度的过程。

  • 分布式定时任务是把分散的、可靠性差的定时任务纳入统一的平台,并实现集群管理调度和分布式部署的一种定时任务的管理方式。

按触发时机分类:

  • 定时任务:特定时间触发,比如今天15:06执行
  • 延时任务:延时触发,比如10s后执行
  • 周期任务:固定周期时间,或固定频率周期调度触发,比如每天12点或者每隔5s执行

特点

  • 自动化:全自动完成定时任务的认度和执行
  • 平台化:基于平台化的思维管控系列的分布式定时任务
  • 分布式:在分布式系统环境下运行任务调度,突破单机定时任务的性能瓶颈
  • 伸缩性:采用集群方式部署,可随时按需扩缩容
  • 高可用:单点故障不影响最终任结果,可以做到故障转移

执行方式

  • 单机任务:随机触发一台机器执行任务,适用于计算量小、并发度低的任务

后端框架的剖析

架构

架构,又称软件架构

  • 是有关软件整体结构与组件的抽象描述
  • 用于指导软件系统各个方面的设计

单机架构

软件系统需要具备对外提供服务,单机,就是把所有功能都实现在一个进程里,并部署在一台机器上

优点:

  • 简单

问题

    • C10K问题(Concurrent 10,000 Connection):服务器如何支持10K个并发连接,进行高性能网络编程。解决方式:采用IO复用模型epoll方法,在调用返回时,只给应用提供发生了状态变化的文件句柄,不需要轮询fd(文件描述符)
  • 运维需要停服

单体、垂直应用|垂直切分

单体架构:分布式部署 垂直应用架构:按应用垂直切分的单体 优点:

  • 水平扩容
  • 运维不需要停服 问题:
  • 职责太多,开发效率不高
  • 爆炸半径大

SOA、微服务|水平切分

S0A(Service-0riented Architecture)

后端开发与迭代

了解开发流程

复杂项目没有流程会有什么问题

  • 需求阶段:每个人都有自己的想法,团队决策需要有一个过程
  • 开发阶段:多人/多端协作开发,每个人有自己的安排,相互配合需要有一个流程
  • 测试阶段:产物怎样交付,测试如何开展,BUG怎么修都需要流程
  • 发布阶段:怎样确保发布过程平稳丝滑,版本和流量如何控制,需要有规范
  • 运维阶段:线上问题如何应急响应,处理用户反馈和线上问题需要有流程

瀑布模型

需求、开发、测试、发布、运维,一个阶段完全好了,再到下一个

  • 传统的线性开发模型,按顺序依次进行需求分析、系统设计、编码、测试和部署。
  • 每个阶段的结果作为下一个阶段的输入。
  • 瀑布模型的突出缺点是不适宜用户需求的变化
  • 需求一旦确认,较难进行修改。
  • 适用于需求较为稳定、项目较小的情况。

敏捷开发

更注重的是个体的互动、工作的软件、客户合作、响应变化

  • 以小团队快速迭代
  • 团队成员之间的合作更加紧密
  • 以人为本,和用户沟通

更现代的流程模型

网络接入

域名系统

使用域名系统来代替 hosts 文件

关于域名空间: - 域名空间被组织成树形结构 - 域名空间通过划分zone的方式进行分层授权管理 - 全球公共域名空间仅对应一棵树 - 根域名服务器:查询起点 - 域名组成格式:[a-zA-Z0-9-],以点划分label

顶级域gTLD(general Top-level Domains):gov政府.edu教育.com商业.mil军事.org非盈利组织

DNS服务器

DNS查询过程

比如这里的网络客户端想要访问163.com域名,首先会访问本地的DNS服务器,看看有没有163.com域名的解析记录,第一次访问都不会有解析记录的,如果没有解析记录会依次向根、顶级域进行解析以及保存在本地,以便于下次查询

DNS记录类型

  • A/AAAA:IP指向记录,用于指向IP,前为IPv4记录,后者为IPv6记录
  • CNAME:别名记录,配置值为别名或主名,客户端根据别名继续解析以提取IP地址
  • TXT:文本记录,购买证书时需要
  • MX:邮件交换记录,用于指向邮件交换服务器
  • NS:解析服务器记录,用于指定哪台服务器对于该域名解析
  • SOA 记录:起始授权机构记录,每个zon要权威服务器的记录,有且仅有唯一的一条SOA记录,SOA是描述zone属性以及主

接入HTTPS协议

由于HTTP是明文传输,很容易被截取,因此有了HTTPS

消息队列

消息队列

(听不懂,不是人听的,内容的很奇怪,像初见,又像告别,又像是重逢,能看懂并且记下来都是神人了)

消息队列(MQ),指保存消息的一个容器,本质是个队列。要想称之为消息队列,这个队列要支持 高吞吐高并发 并且 高可用

Kafka

Kafka 的使用

  1. 首先需要创建一个 Kafka 集群;
  2. 在这个集群中创建一个 Topic,并且设置好分片数量;
  3. 编写生产者逻辑,引入对应语言的 SDK,配置好集群和 Topic 等参数,初始化一个生产者,调用 Send 方法发送消息;
  4. 编写消费者逻辑,引入对应语言的 SDK,配置好集群和 Topic 等参数,初始化一个消费者,调用 Poll 方法接收消息。

Kafka的原理

Go 框架三件套

Gorm 的基本使用

相关文档 https://gorm.io/zh_CN/docs/index.html

gorm目前支持 MySQL、SQLServer、PostgreSQL、SQLite

以 MySQL 为例:

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

或者可以更详细的配置:

db, err := gorm.Open(mysql.New(mysql.Config{
  DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
  DefaultStringSize: 256, // string 类型字段的默认长度
  DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
  DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
  DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
  SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{})

创建数据

对象存储

我在青训营看完这章对象存储TOS感觉对理论性的知识有了一定了解吧,太理论了,让我复述一遍可能都做不到

我在网上查阅资料后得知

  • TTencent,表示这是腾讯云提供的服务。

  • OObject,表示对象存储(Object Storage),是一种存储非结构化数据的技术。

  • SStorage,表示存储服务。

首先开头以抖音短视频为例

架构大概分为 片源 -> 转码 -> 审核 -> 播放

但是短视频系统要承载非常多的用户访问量,根据未来的可能的用户数量,做了简单数学计算,结果发现存储量非常之大:

  • 每天: 432块4tb磁盘

  • 每月:12960块4tb磁盘

  • 每年: 157680块4tb盘

对于这么大的访问量,我们需要一个合适的存储去承载数据,这个储存需要满足以下三个条件:

  • 海量

  • 易用

  • 便宜

然后列举了四个存储系统

  • 单机存储——>不支持海量,适合的数据类型(单击文件)——>不行

  • 单机数据库——> 不支持海量,只支持结构化和半结构化数据——>不行

  • 分布式数据库——>支持海量,但是单条记录存储的容量太少——>不行

  • 分布式存储——> 大数据计算中间结果/视频/图片——>行

分布式文件系统(HDFS)

  • 海量:支持PB——>EB海量存储

  • 易用:伪Posix文件接口,开发略微复杂,非云原生,搭建维护麻烦,视频、图片相关生态接入略微复杂

  • 便宜:使用普通x86服务器,成本低

分布式对象存储TOS

  • 海量:支持>eb海量存储

  • 易用:RestFul HTTP接口,开发极其简单,云原生,按需申请使用

  • 便宜:使用普通x86服务器,具备冷热数据分级存储能力,成本更低

TOS 的接口

Mkdirs创建文件夹
Append:写
GET:下载对象
HEAD:查看对象上传
PUT:上传对象
DELETE:删除对象

TOS 中Bucket/Object语义

Bucket:存储对象的桶,可类比一下
Object:对象,包含以下三个部分
key:对象的名字,可类比于Map的key
Data:对象的内容,例如视频、图片内容
MetaData:对象的一些元信息

数据结构与算法

排序

Insertion Sort 插入排序

将元素不断插入已经排序好的 array 中

  • 起始只有一个元素5,其本身是一个有序序列
  • 后续元素插入有序序列中,即不断交换,直到找到第一个比其小的元素
BestAvgWorst
O(n)O(n^2)O(n^2)

缺点

  • 平均和最坏情况的时间复杂度高达 O(n^2)

优点

  • 最好情况时间复杂度为O(n)

总结:插入排序平均和最坏情况时间复杂度都是 O(n^2)

Quick Sort 快速排序

代码优化

高质量编程

编写的代码能够达到正确可靠、简洁清晰的目标可称为高质量代码

  • 各种边界条件是否考虑完备
  • 异常情况处理,稳定性保证
  • 易读易维护

编程原则

简单性

  • 消除“多余的复杂性”,以简单清晰的逻辑编写代码
  • 不理解的代码无法修复改进 可读性
  • 代码是写给人看的,而不是机器
  • 编写可维护代码的第一步是确保代码可读 生产力
  • 团队整体工作效率非常重要

编写规范

注释

公共符号始终要注释

Go语言

基础语法

  • 变量
    • var 变量名 = 值
    • int(数据类型) 变量名 = 值
    • 变量名 := 值
  • 常量
    • const 变量名 = 值
    • const 变量名 数据类型 = 值

判断 IF

package main  
  
import "fmt"  
  
func main() {  
    if 7%2 == 0 {  
       fmt.Println("7 is even")  
    } else {  
       fmt.Println("7 is odd")  
    }  
  
    if 8%4 == 0 {  
       fmt.Println("8 is divisible by 4")  
    }  
  
    if num := 9; num < 0 {  
       fmt.Println(num, "is negative")  
    } else if num < 10 {  
       fmt.Println(num, "has l digit")  
    } else {  
       fmt.Println(num, "has multiple digits")  
    }  
}

循环 For

在 Go 中没有 while 和 do while,只有 for 循环

RDBMS

ACID

ACID

  • 原子性( tomicity):事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
  • 一致性( onsistency):数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性,每个操作都必须是合法的。
  • 隔离性( solation):多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果,类似于串行操作。
  • 持久性(Curability):在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

模型

1960s,传统的文件系统已经不能满足人们的需要,数据库管理系统(DBMS)应运而生DBMS:按照某种数据模型来组织、存储和管理数据的仓库。所以通常按照数据模型的特点将传统数据库系统分成网状数据库、层次数据库和关系数据库三类。

网状模型

把每个数据作为一个节点,构成一个网状的结构,每个父节点可以有多个子节点,一个子节点也可以有多个父节点,多对多

层次模型

层次模型是一个树形模型,层次模型和网状模型特别相像,最大的不同是每个父节点可以有多个子节点,但每个子节点只能有一个父节点,一对多

关系模型

数据库

ARID磁盘阵列

Q : 单机存储系统怎么做到高性能/高性价比/高可靠性

A : R(edundant) A(array) I(nexpensive) D(isks)

ARID的使用背景

  • 单块大容量磁盘的价格 > 多块小容量磁盘
  • 单块磁盘的写入性能 < 多块磁盘的并发写入功能
  • 单块磁盘的容错能力有限,不够安全

常见ARID方案

  • RAID 0
    • 多块磁盘简单组合
    • 数据条带化存储,提高磁盘带宽
    • 没有额外的容错设计 例如一条1G的数据1被拆成两条512M数据,分别写道磁盘1和磁盘2上,然后磁盘1和磁盘2的第一个512M共同组成数据1
  • RAID 1
    • 一块磁盘对应着一块额外的磁盘
    • 真实空间利用率仅50%
    • 容错能力强 RAID 1和RAID 0是两个极端,把一条数据copy一份放在两个磁盘上
  • RAID 0 + 1
    • 结合了 RAID 0 和 RAID 1
    • 真实空间利用率只有50%
    • 容错能力强,写入宽带好 例如说,现在有四块磁盘,可以把它两两组成一个 RAID 0,然后再把组成的单元用 RAID 1 组成起来或者组成 RAID 1,然后再用 RAID 0 组成起来,虽然空间利用率还是只有50%,但是还用上了 RAID 1 的条带化写入,并发存储,写入带宽能翻几倍。

数据库

关系 = 集合 = 任意元素组成的若干有序偶对反应了事物间的关系

Git

项目初始化

在study文件下创建一个git,名字叫blog

mkdir study
cd study
git init blog

其他参数

--initial-branch  初始化的分支
--bare  创建一个裸仓库(纯 Git 目录,没有工作目录)
--template  可以通过模板来创建预先构建好的自定义 git 目录

Git Config

不同级别的 Git 配置