note5


==============================================================================================

1、熟悉Golang编程语言,依赖管理go mod、并发编程goroutine、channel、GMP协程调度模型 context与waitgroup,互斥及读写锁等
oom
--new make 都是用来分配内存地址的
new,它返回的永远是类型的指针,指向分配类型的内存地址,new用于类型的内存分配,并且内存置为零
make只用于slice、map以及channel的初始化(非零值),make返回的还是这三个引用类型本身;而new返回的是指向类型的指针

--逃逸分析
栈:在程序中,每个函数块都会有自己的内存区域用来存自己的局部变量(内存占用少)、返回地址、返回值之类的数据,这一块内存区域有特定的结构和寻址方式,
大小在编译时已经确定,寻址起来也十分迅速,开销很少。这一块内存地址称为栈。栈是线程级别的,大小在创建的时候已经确定

堆:在程序中,全局变量、内存占用大的局部变量、发生了逃逸的局部变量存在的地方就是堆

如果一个函数返回的是一个(局部)变量的地址,这个变量可能被全局变量引用,那么这个变量就发生逃逸
逃逸 会增加GC压力


-----------------------------------------go mod------------------------------------------------
golang 1.11 新加的特性
设置
go env -w GOBIN=/Users/youdi/go/bin
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct // 使用七牛云的

modules功能启用时,依赖包的存放位置变更为$GOPATH/pkg,允许同一个package多个版本并存,且多个项目可以共享缓存的 module

go mod init 初始化项目
go mod tidy 拉取缺少的模块,移除不用的模块
go mod edit 编辑go.mod

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

go.mod 提供了module, require、replace和exclude 四个命令

module 语句指定包的名字(路径)
require 语句指定的依赖项模块
replace 语句可以替换依赖项模块
exclude 语句可以忽略依赖项模块

https://www.jianshu.com/p/760c97ff644c

---------------------------------------goroutine channel-----------------------------------------
goroutine的概念类似于线程,但 goroutine是由Go的运行时(runtime)调度和管理的。Go程序会智能地将 goroutine
中的任务合理地分配给每个CPU。Go语言之所以被称为现代化的编程语言,就是因为它在语言层面已经内置了调度和上下文切换的机制
开启关键字 go

channel
channel是一种类型,一种引用类型 var 变量 chan 元素类型, 声明的通道后需要使用make函数初始化之后才能使用
make(chan 元素类型, [缓冲大小]) 接收发送符号 <-,关闭close(ch)

Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信
goroutine是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制


----------------------------------------GMP协程调度模型-------------------------------------------
GPM
G:G很好理解,就是个goroutine
P:P管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界),
P会对自己管理的goroutine队列做一些调度(比如把占用CPU时间较长的goroutine暂停、运行后续的goroutine等等)
当自己的队列消费完了就去全局队列里取,如果全局队列里也消费完了会去其他P的队列里抢任务。
M(machine)是Go运行时(runtime)对操作系统内核线程的虚拟, M与内核线程一般是一一映射的关系, 一个groutine最终是要放到M上执行的;

P与M一般也是一一对应的。他们关系是: P管理着一组G挂载在M上运行。当一个G长久阻塞在一个M上时,runtime会新建一个M,
阻塞G所在的P会把其他的G 挂载在新建的M上。当旧的G阻塞完成或者认为其已经死掉时 回收旧的M。
P的个数是通过runtime.GOMAXPROCS设定(最大256),Go1.5版本之后默认为物理线程数。 在并发量大的时候会增加一些P和M,但不会太多,切换太频繁的话得不偿失
单从线程调度讲,Go语言相比起其他语言的优势在于OS线程是由OS内核来调度的,goroutine则是由Go运行时(runtime)自己的调度器调度的,
这个调度器使用一个称为m:n调度的技术(复用/调度m个goroutine到n个OS线程)

Go语言中的操作系统线程和goroutine的关系
一个操作系统线程对应用户态多个goroutine。
go程序可以同时使用多个操作系统线程。
goroutine和OS线程是多对多的关系,即m:n。

补充
协程原理
协程在go里面来说就是goroutine 完全运行在用户态的(切换开销很小) 借鉴了m:n模型。golang采用了MPG模型管理协程
M:内核线程
G:代表一个goroutine
P:Processor,处理器,用来管理和执行goroutine的
G-M-P:
P的个数取决于设置的GOMAXPROCS,go新版本默认使用最大内核数,比如你有8核处理器,那么P的数量就是8
M的数量和P不一定匹配,可以设置很多M,M和P绑定后才可运行,多余的M处于休眠状态。
P包含一个LRQ(Local Run Queue)本地运行队列,这里面保存着P需要执行的协程G的队列
除了每个P自身保存的G的队列外,调度器还拥有一个全局的G队列GRQ(Global Run Queue),这个队列存储的是所有未分配的协程G
https://studygolang.com/articles/11627
https://www.jianshu.com/p/cc3c0fefee43
 



-----------------------------------------context与waitgroup--------------------------------------
控制并发的两种方式
waitgrop方式
wg.Add(n)
wg.Done(n)
wg.Wait() 阻塞程序 等countDown数为0继续执行
此方式:创建一个子协程后,主协程无法控制子协程,只能等待,不能因为时间过长而发送信号通知子协程停止执行

context.WithCancel方法用于创建一个可以发送取消信号的Context,它的入参需要一个父Context,此处使用了
context.Background(),它正是根Context。调用cancel方法,会通过ctx.Done()通知子协程,然后使用select处理此信号

https://www.jianshu.com/p/eefac474ce0b

---------------------------------------互斥及读写锁-----------------------------------------------
互斥锁:互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待锁;
lock sync.Mutex -》lock.Lock() VS lock.Unlock()

读写锁分:读锁和写锁。当一个goroutine获取读锁之后,其他的goroutine如果是获取读锁会继续获得锁,
如果是获取写锁就会等待;当一个goroutine获取写锁之后,其他的goroutine无论是获取读锁还是写锁都会等待
读的场景远远大于写的场景用读写锁
读锁:wLock sync.RWMutex -》 rwLock.RLock() VS rwLock.RUnlock()
写锁:wLock sync.RWMutex -》 rwLock.Lock() VS rwLock.UnLock()







==============================================================================================
2、web框架gin、 beego、数据库操作gorm、xorm、跨域认证标准解决方案Jwt
-----------------------------------------gin--------------------------------------------------
Gin在性能方面较beego更好
如果项目的规模不大,业务相对简单,适用Gin

不支持正则路由

需要开发者自己实现mvc

-----------------------------------------beego--------------------------------------------------
Beego在业务方面较Gin支持更多
在业务更加复杂的项目,适用beego
在需要快速开发的项目,适用beego

支持正则路由

beego支持完整的mvc
M:Model,beego orm,把数据库数据变成object
-----------------------------------------gorm xorm-------------------------------------------------

------------------------------------------Jwt------------------------------------------------
Cookie-Session模式实现用户认证依赖于客户端(浏览器)保存Cookie,并且需要在服务端存储用户的session数据,
在移动互联网时代,我们的用户可能使用浏览器也可能使用APP来访问我们的服务,我们的web应用可能是前后端分开部署在不同的端口,
有时候我们还需要支持第三方登录,这下Cookie-Session的模式就有些力不从心了

JWT就是一种基于Token的轻量级认证模式,服务端认证通过后,会生成一个JSON对象,经过签名后得到一个Token(令牌)再发回给用户,
用户后续请求只需要带上这个Token,服务端解密之后就能获取该用户的相关信息了



==============================================================================================
3、微服务(分而治之 合而用之)开发 gRPC、protobuf序列化文本协议、micro,了解consul服务发现管理
------------------------------------------微服务------------------------------------------------
概念
微服务架构:将复杂的系统使用组件化的方式进行拆分,并使用轻量级通讯方式进行整合的一种设计方法。
微服务:是通过这种架构设计方法拆分出来的一个独立的组件化的小应用。

跨语言 跨平台 通讯格式protobuf
通讯协议 gRPC
调度管理服务发现 consul
微服务的框架 micro
部署 docker
-------------------------------------------RPC-------------------------------------------------

RPC 1.Call ID映射 2.序列化和反序列化 3.网络传输 三个机制实现
概念:指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,
由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

// Client端
// int l_times_r = Call(ServerAddr, Multiply, lvalue, rvalue)
将这个调用映射为Call ID。这里假设用最简单的字符串当Call ID的方法
将Call ID,lvalue和rvalue序列化。可以直接将它们的值以二进制形式打包
把2中得到的数据包发送给ServerAddr,这需要使用网络传输层
等待服务器返回结果
如果服务器调用成功,那么就将结果反序列化,并赋给l_times_r

// Server端
在本地维护一个Call ID到函数指针的映射call_id_map,可以用std::map<std::string, std::function<>>
等待请求
得到一个请求后,将其数据包反序列化,得到Call ID
通过在call_id_map中查找,得到相应的函数指针
将lvalue和rvalue反序列化后,在本地调用Multiply函数,得到结果
将结果序列化后通过网络返回给Client

总结:
Call ID映射可以直接使用函数字符串,也可以使用整数ID。映射表一般就是一个哈希表。
序列化反序列化可以自己写,也可以使用Protobuf或者FlatBuffers之类的。
网络传输库可以自己写socket,或者用asio,ZeroMQ,Netty之类。
-----------------------------------------gRPC-------------------------------------------------
grpc gRPC HTTP2.0 Protobuf
gRPC是由Google主导开发的RPC框架,使用HTTP/2协议并用Protobuf作为序列化工具
https://github.com/grpc/grpc-go grpc示例代码库
https://grpc.io/docs/languages/go/quickstart/ grpc文档
https://github.com/protocolbuffers/protobuf/releases protobuf协议编译器: 安装解压 拷贝到GOPATH/bin 注意include也要拷贝
go get -u google.golang.org/grpc
go get -u github.com/golang/protobuf/protoc-gen-go 生成Go语言代码的工具
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1

---------------------------------------Protobuf------------------------------------------------
一种传输协议或者说结构数据序列化方法,特点:小而快 但人不认识,机器认识,语言无关、平台无关、可扩展的序列化结构数据的方法
--Protobuf语法
syntax = "proto3"; //告诉编译器用proto3 解读
option go_package="go_grpc/pb/person;person"; //go_mod包名开头
package person;

message 类型 key名称 唯一表示
repeated 的使用:被 repeated 标识的字段可以理解为是一个数组
enum 类型使用:枚举用来表示一定范围内具有相同属性的值
enum SEX { //枚举类型 一定要有0
option allow_alias = true; // 数字唯一标识可重复用 WOMAN GIRL
MAN = 0;
WOMAN = 1;
GIRL = 1;
OTHER = 2;
}
SEX sex = 3;
map <string,string> test_map = 5;
reserved "test_map","test"; //变成保留值 以后要用,其他人就不能用了 否则编辑器会报错 (编译不会生成,只给编译器看)

----------------------------------------consul vs etcd-----------------------------------------------
consul用于微服务下的服务治理,主要特点有:服务发现、服务配置、健康检查、键值存储、安全服务通信、多数据中心等。
服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,
他有两种运行模式server和client。每个数据中心官方建议需要3或5个server节点以保证数据安全,同时保证server-leader的选举能够正确的进行。
https://zhuanlan.zhihu.com/p/122340918

etcd是使用Go语言开发的一个开源的、高可用的分布式key-value存储系统,可以用于配置共享和服务的注册和发现


-----------------------------------------micro------------------------------------------------
Go Micro是一个插件式的RPC框架。它用于分布式系统开发

https://www.kancloud.cn/linimbus/go-micro/529030


==============================================================================================
4、熟悉Go内存调优pprof Go性能调优、GC标记染色技术优化
----------------------------------------pprof--------------------------------------------------
pprof :用于系统性能分析
pprof
Golang性能测试工具
关注CPU使用情况(CPU profile)、内存使用情况(Memory Profile(Heap Profile)、报告 goroutines 不在运行状态的情况(Block Profiling)
报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的(Goroutine Profiling)

net/http/pprof 和 runtime/pprof 两种引用方式
net/http/pprof web应用 使用方便
runtime/pprof 可以用来产生 dump 文件,再使用 Go Tool PProf 来分析这运行日志

/debug/pprof/profile:访问这个链接会自动进行 CPU profiling,持续 30s,并生成一个文件供下载
/debug/pprof/heap: Memory Profiling 的路径,访问这个链接会得到一个内存 Profiling 结果的文件
/debug/pprof/block:block Profiling 的路径
/debug/pprof/goroutines:运行的 goroutines 列表,以及调用关系

https://zhuanlan.zhihu.com/p/51559344
https://www.jianshu.com/p/4e4ff6be6af9
------------------------------------------GC-------------------------------------------------
GC垃圾回收机制 标记、清除 内存管理 黑色 灰色 白色
黑色: 对象在这次GC中已标记,且这个对象包含的子对象也已标记
灰色: 对象在这次GC中已标记, 但这个对象包含的子对象未标记
白色: 对象在这次GC中未标记

过程可如下理解:
首先创建三个集合:白、灰、黑。
将所有对象放入白色集合中。
然后从根节点开始遍历所有对象(注意这里并不递归遍历),把遍历到的对象从白色集合放入灰色集合。
之后遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合。
重复 4 直到灰色中无任何对象。
通过write-barrier检测对象有变化,重复以上操作。
收集所有白色对象(垃圾)。


https://www.jianshu.com/p/8b0c0f7772da
https://www.jianshu.com/p/ff3d6da5d71a
==============================================================================================
5、熟悉HTTP、TCP/IP 、socket编程、MQTT (EMQX)
-----------------------------------HTTP TCP/IP---------------------------------------------------
http1.0 http1.1
http1.1:
支持长链接,节约宽带,支持host域(随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主
机(Multi-homed Web Servers),并且它们共享一个IP地址),新增了24个错误状态响应码 如409(表示请求的资源与资源的当前状态发生冲突)
410(表示服务器上的某个资源被永久性的删除)
http2.0:
多路复用技术,做到同一个连接并发处理多个请求;头部数据压缩(HPACK算法对header的数据进行压缩);
HTTP2.0引入了server push,它允许服务端推送资源给浏览器在浏览器明确地请求之前,免得客户端再次
创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络

TCP/IP:四层模型。
①网络接口层:对应物理层和数据链路层。
②网络层
③传输层
④应用层:包括会话层、表示层、应用层

TCP与UDP的区别。
TCP:面向连接,可靠的,速度慢,效率低。
UDP:无连接、不可靠、速度快、效率高

TCP三次握手
所谓三次握手,是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
(1) 第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2) 第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。

TCP 四次挥手
TCP的连接的拆除需要发送四个包,因此称为四次挥手。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个
FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1)TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2)服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器关闭客户端的连接,发送一个FIN给客户端。
(4)客户端发回ACK报文确认,并将确认序号设置为收到序号加1

--------------------------------------socket编程--------------------------------------------------
socket 其实就是操作系统提供给程序员操作「网络协议栈」的接口,
说人话就是,你能通过socket 的接口,来控制协议栈工作,从而实现网络通信,达到跨主机通信
socket 一般分为 TCP 网络编程和 UDP 网络编程

基于 TCP 协议的客户端和服务器工作
服务端和客户端初始化 socket,得到文件描述符;
服务端调用 bind,将绑定在 IP 地址和端口;服务端调用 listen,进行监听;
服务端调用 accept,等待客户端连接;
客户端调用 connect,向服务器端的地址和端口发起连接请求;
服务端 accept 返回用于传输的 socket 的文件描述符;客户端调用 write 写入数据;
服务端调用 read 读取数据;客户端断开连接时,会调用 close,那么服务端 read 读取数据的时候,就会读取到了 EOF,
待处理完数据后,服务端调用 close,表示连接关闭。

这里需要注意的是,服务端调用 accept 时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。
所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket,一个叫作监听 socket,一个叫作已完成连接 socket。
成功连接建立之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

https://www.zhihu.com/question/29637351
-----------------------------------------MQTT----------------------------------------------------
Mqtt是应用层协议
是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上
为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。
其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:
(1)Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);
(2)payload,可以理解为消息的内容,是指订阅者具体要使用的内容。



==============================================================================================
6、熟悉应用消息队列Rabbitmq
-----------------------------------------Rabbitmq---------------------------------------------------
RabbitMQ是一个消息代理:它接受并转发消息

RabbitMQ是一个消息代理(基于amqp协议开发的消息代理):它接受并转发消息
RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的,消息中间件。可以用它来:解耦、异步、削峰。

避免消费者重复消费消息(消费后返回的确认消费,消费队列没收到,就没收删除此消息) :
保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响

简单模式:单发单收
工作模式:一个队列有两个消费者。一个队列中一条消息,只能被一个消费者消费
以上交换机都是默认的direct
订阅与发布模式:Fanout
路由模式:Direct
主题模式:Topic



交换机类型
Fanout (订阅模式|广播模式)
生产者将消息扔给交换机,交换机类型是fanout
不处理路由键,只需要简单的将队里绑定到交换机上
生产者将消息不是直接发送到队列,而是发送到X交换机,发送到交换机的消息都会被转发到与该交换机绑定的所有队列上
Fanout交换机转发消息是最快的

例:有一个商城,我们新添加一个商品后,可能同时需要去更新缓存和数据库

Direct(路由模式)简单模式、
生产者将消息发送给交换机,消息携带具体的routingkey。交换机类型是direct,接收到消息中的routingkey,比对与之绑定的队列的routingkey,分发到不同的队列上
所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue。
消息传递时,RouteKey必须完全匹配才会被队列接收,否则该消息会被抛弃。
例:商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,不用刷新缓存


Topic (通配符模式)(主题模式)
路由模式的一种,路由功能添加了模糊匹配。星号(*)代表1个单词,#号(#)代表一个或多个单词。具体可参考路由模式
所有发送到Topic Exchange的消息被转发到所有管线RouteKey中指定Topic的Queue上
Exchange将RouteKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic

有一个商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,数据库包含了主数据库mysql1和从数据库mysql2的内容,不用刷新缓存

Headers(键值对模式)
headers 也是根据规则匹配, 相较于 direct 和 topic 固定地使用 routing_key , headers 则是一个自定义匹配规则的类型.
在队列与交换器绑定时, 会设定一组键值对规则, 消息中也包括一组键值对( headers 属性), 当这些键值对有一对, 或全部匹配时, 消息被投送到对应队列.

简单模式:生产者,一个消费者,一个队列
工作模式:生产者,多个消费者,一个队列
订阅与发布模式(fanout):生产者,一个交换机(fanoutExchange),没有路由规则,多个消费者,多个队列
路由模式(direct):生产者,一个交换机(directExchange),路由规则,多个消费者,多个队列
主题模式(topic):生产者,一个交换机(topicExchange),模糊匹配路由规则,多个消费者,多个队列

RabbitMQ中实现RPC的机制是:
一. 生产者发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14个属性,这些属性会随着消息一起发送)
中设置两个属性值replyTo(一个Queue名称,用于告诉消费者处理完成后将通知我的消息发送到这个Queue中)和correlationId
(此次请求的标识号,消费者处理完成后需要将此属性返还,生产者将根据这个id了解哪条请求被成功执行了或执行失败)。
二. 消费者收到消息并处理。
三. 消费者处理完消息后,将生成一条应答消息到replyTo指定的Queue,同时带上correlationId属性。
四. 生产者之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理。
https://www.cnblogs.com/woadmin/p/10537174.html


==============================================================================================
7、熟悉全文搜索引擎Elasticsearch
-----------------------------------------Elasticsearch---------------------------------------------------

全文搜索引擎
节点 - 它指的是Elasticsearch的单个正在运行的实例
集群 - 它是一个或多个节点的集合。 集群为整个数据提供跨所有节点的集合索引和搜索功能
索引----它是不同类型的文档和文档属性的集合--数据库
类型----它是共享同一索引中存在的一组公共字段的文档的集合--表
文档----它是以JSON格式定义的特定方式的字段集合。每个文档都属于一个类型并驻留在索引中--表中的记录
属性----列




==============================================================================================
8、Git 版本控制器
-----------------------------------------Git---------------------------------------------------
如果代码出现bug,你们是如何解决的?
创建一个bug分支,然后进行bug处理,处理完毕后,合并到review分支,组长review成功后才能够合并到master
合并完成之后删除bug分支
回到dev分支继续开发。

你使用过git stash命令吗?你一般什么情况下会使用它?
命令git stash是把工作区修改的内容存储在栈区。
以下几种情况会使用到它:
解决冲突文件时,会先执行git stash,然后解决冲突;
遇到紧急开发任务但目前任务不能提交时,会先执行git stash,然后进行紧急任务的开发,然后通过git stash pop取出栈区的内容继续开发;
切换分支时,当前工作空间内容不能提交时,会先执行git stash再进行分支切换;

https://www.cnblogs.com/andy0816/p/12508162.html




==============================================================================================
9、容器技术docker
-----------------------------------------docker vs K8S---------------------------------------------------
docker就是创建容器的工具,docker包含容器,镜像,仓库。容器就是原始文件,镜像就是复制容器来的,仓库就是储存镜像的
容器和虚拟机
相同:
容器和虚拟机一样都对物理硬件资源进行共享
容器和虚拟机生命周期相似 :创建 运行 暂停 关闭等
都可以安装各种应用 redis nginx 等
创建后都会存储在宿主机上
不同点:
虚拟机是一个完整的操作系统,容器需要操作系统做支撑的,本质上是一系列进程的组合
容器不需要额外的资源来管理,虚拟机有额外的更多性能消耗
容器创建启动等都容易的多



docker 是什么
一个开源的容器引擎,基于LCK容器技术,使用golang语言开发
docker 可轻松为任何应用创建可轻量级的、可移植的、自给自足的容器

docker提供了在一个完全隔离的环境中打包和运行应用程序的能力,这个隔离的环境成为容器
由于容器的隔离性和安全性,因此可以在一个主机(也叫住宿)上同时运行多个相互隔离的容器,互不干扰。

为什么用docker
保证程序运行环境的一致性
降低配置开发环境和生产环境复杂度和成本
实现程序的快速部署和分发
还可以避免甩锅

CS 结构 client (终端命令行) 通过REST API 与serve端进行通信的接口 sever 守护进程等待客户端发送命令 执行

四大核心技术:
镜像、容器、数据卷、网络
终端命令发送到 docker-host主机(docker服务端) 执行命令:如(docker pull)拉取镜像
镜像:一个docker的可执行文件,它包含运行程序所需的所有代码、依赖库、环境变量和配置文件等
容器:镜像被运行起来的实例
数据卷:容器和宿主机之间、容器和容器之间共享存储方式,类似于虚拟机和主机之间的共享文件目录 (容器内数据直接映射到本地主机环境)
网络:外部或容器之间互相访问的网络方式,如HOST模式,bridge模式

数据卷容器
docker create -v 容器卷目录 --name name1 image_id
docker run -it --name name2 -volumes-from name1 image_id 两个容器共享数据卷


docker 数据备份
创建一个挂载数据卷容器的容器
挂载宿主机本地目录作为备份数据卷
将数据卷容器的内容备份到宿主机本地目录挂载的数据卷中
完成备份操作后销毁刚创建的容器
docker run --rm --volumes-from name1[数据卷容器name/ID] -v
/home/backup[宿主机目录] :/backup[容器目录] image[镜像名称]
后面是备份命令 tar -zcPF /backup/data.tar.gz /data



网络模式
bridge 同一主机下的容器都在一个网络下,彼此之间可以通过。利用宿主机网卡通信,因为涉及到网络转换所以会造成资源消耗,网络效率低
映射
桥接网络

host 容器与宿主机共享网络
none 最纯粹,可自由定制网络
container模式 使用以创建的容器网络 类似局域网 容器和容器共享网络
overlay 容器彼此不在同一网络,而且可以互相通行 (docker内部)


dockerfile
FROM golang:alpine

# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# 移动到工作目录:/build
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 将我们的代码编译成二进制可执行文件app
RUN go build -o app .

# 移动到用于存放生成的二进制文件的 /dist 目录
WORKDIR /dist

# 将二进制文件从 /build 目录复制到这里
RUN cp /build/app .

# 声明服务端口
EXPOSE 8888

# 启动容器时运行的命令



k8s 基于容器的集群管理平台(K8S是用来管理容器的)
一个K8S系统,通常称为一个K8S集群(Cluster)。
这个集群主要包括两个部分:一个Master节点,一群Node。
Master节点主要还是负责管理和控制。Node节点是工作负载节点,里面是具体的容器
pod包含各个功能的容器,pod在node运行,master管理node。
Master节点包括API Server、Scheduler、Controller manager、etcd。
API Server是整个系统的对外接口,供客户端和其它组件调用,相当于“营业厅”。
Scheduler负责对集群内部的资源进行调度,相当于“调度室”。
Controller manager负责管理控制器,相当于“大总管”。
Node 是 k8s 的工作节点,Node 一般是一个虚拟机或者物理机,每个 node 上都运行三个服务:docker、kubelet、 kube-proxy
docker 就是创建容器的
kubelet 是一个管理系统,它管理本个node上的容器的生命周期,监视指派到它所在Node上的Pod,包括创建、修改、监控、删除等
kube-proxy 是管理 service 的访问入口,即:要负责为Pod对象提供代理

--
master  主要工作:调度应用程序、维护应用程序的所需状态,扩展应用程序和滚动更新(先运行新容器2.0,所有请求都交到新容器,在关闭旧容器1.0)
node 主要 运行容器应用 负责监听并汇报容器的状态,同时根据master的要求管理容器的生命周期。
每个node都有kubelet(管理节点并与master进行通信的代理)
pob(资源对象) k8s的最小工作单元 每个pod可能包含多个容器 这些容器使用同一个网络namespace(即:相同的ip和port空间,可直接用localhost通信)
这些容器也可以共享存储 k8s挂载 volume到pod 就是将volume挂载到pob 中的每个容器。

controller(Deployment、ReplicaSet.....Job 多种controller) 管理pob的多个副本并确保pob按期望的状态运行,一般是Deployment
service 定义了外界访问一组特定pob的方式 有自己的ip和端口 ,service为pob提供了负载均衡
k8s运行容器(pob)和访问容器(pob) 这两项任务分别由 controller 和 service 执行
Namespace 多个用户或者项目使用同一个k8s ,即:可以将物理的集群(Cluster)逻辑上划分为多个虚拟的Cluster,可以将controller pod 等创建的资源划分开
默认有两个 default (创建资源时不指定namespace 将被放到这个namespace)、kube-system(k8s自己创建的系统资源放在此namespace)

k8s流程
1、准备好对应的yanl文件,通过kubectl发送到Api Server中
2、Api Server接收到客户端的请求将请求内容保存到etcd中
3、Scheduler会监测etcd,发现没有分配节点的pod对象通过过滤和打分筛选出最适合的节点运行pod
4、节点会通过conteiner runntime 运行对应pod的容器以及创建对应的副本数
5、节点上的kubelet会对自己节点上的容器进行管理
6、controler会监测集群中的每个节点,发现期望状态和实际状态不符合的话,就会通知对应的节点
7、节点收到通知,会通过container runtime来对pod内的容器进行收缩或者扩张

对于容器来说,管理的单位是容器
对于k8s来说,管理的是一个pod应用
一个pod上可以运行多个容器,可以将pod理解为一个虚拟机,一个虚拟机上运行了多个容器

==============================================================================================
10、熟悉微信公众号、小程序开发,微信支付开发

...


==============================================================================================
11、熟悉 MySql,配置管理、分表分库、主从同步,分布式锁等,具备较好的数据库设计及优化能力

-------------------------------------------分表分库----------------------------------------------
先垂直分,后水平分
垂直 :就是分拓展表,分开常用的与不常用的字段为两个表
水平 根据ID 取模 命名表明 user_1(1-100000)、user_2(100001-200000)
-------------------------------------------主从同步---------------------------------------------
MySQL主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新
1.Master 数据库只要发生变化,立马记录到Binary log 日志文件中
2.Slave数据库启动一个I/O thread连接Master数据库,请求Master变化的二进制日志
3.Slave I/O获取到的二进制日志,保存到自己的Relay log 日志文件中。
4.Slave 有一个 SQL thread定时检查Realy log是否变化,变化那么就更新数据

--配置文件
master 配置文件: 打开binlog服务,设置下日志格式,日志文件大小等配置,还可以设置忽略那些库的同步等等
slave :binlog relaylog 服务
--进入master创建复制用户并授权
--查看master的状态
--配置从库
CHANGE MASTER TO
MASTER_HOST = '172.17.0.3',
MASTER_USER = 'repl_user',
MASTER_PASSWORD = 'repl_passwd',
MASTER_PORT = 3307,
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=120,
MASTER_RETRY_COUNT = 60,
MASTER_HEARTBEAT_PERIOD = 10000;
# MASTER_LOG_FILE='mysql-bin.000005',#与主库File 保持一致
# MASTER_LOG_POS=120 , #与主库Position 保持一致

--------------------------------------------分布式锁---------------------------------------------
控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。
如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止
彼此干扰来保证一致性,这个时候,便需要使用到分布式锁
基于数据库的实现方式的核心思想是:在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,
想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁

-----------------------------分布式事务----------------------------------------------
分布式事务
分布式系统会把一个应用系统拆分为可独立部署的多个微服务,
因此服务之间需要远程协作才能完成事务操作,这种分布式系统环境下有不同服务之间通关网络远程协作完成事务称之为分布式事务

产生场景
1)微服务架构,微服务之间通过远程调用完成事务操作。比如订单服务和库存服务,下单的同时订单服务请求库存服务减少库存
2)单体系统访问多个数据库实例也会产生分布式事务。
3)多服务访问同一个数据库实例 原因:两个微服务持有了不同的数据库链接进行数据库操作,此时产生分布式事务

解决方案
2PC 、Seata 、TCC 、可靠消息最终一致性、最大努力通知方案
XA方案(2PC):
整个 2PC 的事务流程涉及到三个角色 AP、RM、TM。AP 指的是使用 2PC 分布式事务的应用程序;RM 指的是资源管理器,它控制着分支事务;TM 指的是事务管理器,它控制着整个全局事务。
(1)在准备阶段 RM 执行实际的业务操作,但不提交事务,资源锁定
(2)在提交阶段 TM 会接受 RM 在准备阶段的执行回复,只要有任一个RM执行失败,TM 会通知所有 RM 执行回滚操作,否则,TM 将会通知所有 RM 提交该事务。提交阶段结束资源锁释放。
XA方案的问题
需要本地数据库支持XA协议。
资源锁需要等到两个阶段结束才释放,性能较差。

Seata方案
Seata它是一个是开源的分布式事务框架,
Transaction Coordinator(TC):事务协调器,它是独立的中间件,需要独立部署运行,它维护全局事务的运行状态,接收 TM 指令发起全局事务的提交与回滚,负责与 RM 通信协调各各分支事务的提交或回滚。
Transaction Manager(TM): 事务管理器,TM 需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向 TC 发起全局提交或全局回滚的指令。
Resource Manager(RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器 TC 的指令,驱动分支(本地)事务的提交和回滚。

用户服务的 TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
用户服务的 RM 向 TC 注册分支事务,该分支事务在用户服务执行新增用户逻辑,并将其纳入 XID 对应全局事务的管辖。
用户服务执行分支事务,向用户表插入一条记录。
逻辑执行到远程调用积分服务时(XID 在微服务调用链路的上下文中传播)。积分服务的 RM 向 TC 注册分支事务,该分支事务执行增加积分的逻辑,并将其纳入 XID 对应全局事务的管辖。
积分服务执行分支事务,向积分记录表插入一条记录,执行完毕后,返回用户服务。
用户服务分支事务执行完毕。
TM 向 TC 发起针对 XID 的全局提交或回滚决议。
TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
注意 : 第一阶段就提交了分支事务,因为有UNDO_LOG表(每一次本地事务的回滚数据)RM会读取他进行数据恢复,所以减少了XA方案的长时间的占用资源(加锁)  他要等两阶段提交完成才释放资源
https://www.jianshu.com/p/044e95223a17


TCC方案
预处理try 确认confirm 取消cancel
Try 阶段是做完业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的 Confirm 一起才能真正构成一个完整的业务逻辑。
Confirm 阶段是做确认提交,Try 阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用 TCC 则认为 Confirm 阶段是不会出错的。即:只要 Try 成功,Confirm 一定成功。若 Confirm 阶段真的出错了,需引入重试机制或人工处理。
Cancel 阶段是在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,采用 TCC 则认为 Cancel 阶段也是一定成功的。若 Cancel 阶段真的出错了,需引入重试机制或人工处理


如果拿 TCC 事务的处理流程与 2PC 两阶段提交做比较,2PC 通常都是在跨库的 DB 层面,而 TCC 则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据操作的粒度,使得降低锁冲突、提高吞吐量成为可能。
而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现 Try、Confirm、Cancel 三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。


可靠消息最终一致性方案
本地消息表方案:本地事务保证数据业务操作和消息的一致性,然后通过定时任务将消息发送至消息中间件,待确认消息发送给消费方成功再将消息删除

最大努力通知方案
账户系统调用充值系统接口
充值系统完成支付处理向账户发起充值结果通知,若通知失败,则充值系统按策略进行重复通知
账户系统接收到充值结果通知修改充值状态
账户系统未接收到通知会主动调用充值系统的接口查询充值结果

https://www.cnblogs.com/dyzcs/p/13780668.html

---------------------------------------------优化--------------------------------------------
对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.
应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
减少或避免 like
索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会
重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要

---------------------------------------------事务----------------------------------------------
原子性、一致性、隔离性(读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable))、持久性
start transaction
commit
rollback
脏读 不可重复读 幻读
Read uncommitted √ √ √
Read committed × √ √
Repeatable read × × √
Serializable × × ×
---------------------------------------------存储引擎---------------------------------------------
MyISAM与InnoDB存储引擎的主要特点

MyISAM存储引擎的特点是:
表级锁、不支持事务和全文索引,适合一些CMS内容管理系统作为后台数据库使用,但是使用大并发、重负荷生产
系统上,表锁结构的特性就显得力不从心

MyISAM索引结构: MyISAM索引用的B+ tree来储存数据,MyISAM索引的指针指向的是键值的地址,地址存储的是数据。
B+Tree的数据域存储的内容为实际数据的地址,也就是说它的索引和实际的数据是分开的,只不过是用索引指向了实际的数据,
这种索引就是所谓的非聚集索引

InnoDB存储引擎的特点是:
行级锁、事务安全(ACID兼容)、支持外键、不支持FULLTEXT类型的索引(5.6.4以后版本开始支持FULLTEXT类型的索引)。
InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全存储引擎。InnoDB是为处理巨大量时拥有最大性能而
设计的。它的CPU效率可能是任何其他基于磁盘的关系数据库引擎所不能匹敌的

InnoDB引擎的索引结构:也是B+Treee索引结构。Innodb的索引文件本身就是数据文件,即B+Tree的数据域存储的就是实际的数据,
这种索引就是聚集索引。这个索引的key就是数据表的主键,因此InnoDB表数据文件本身就是主索引
InnoDB的辅助索引数据域存储的也是相应记录主键的值而不是地址,所以当以辅助索引查找时,会先根据辅助索引找到主键,
再根据主键索引找到实际的数据。所以Innodb不建议使用过长的主键,否则会使辅助索引变得过大

==============================================================================================
12、熟练redis使用,数据结构,并发锁、过期策略、持久化、分布式锁

------------------------------------------数据结构----------------------------------------------
String—字符串 不仅可以是 String,也可以是数字
使用场景:常规计数等
Hash——字典(哈希) Hash是一个健值对集合,是一个String类型的key与value的映射表,特别适合用于存储对象
使用场景:存储、读取、修改用户属性
List——列表
使用场景:最新消息排行(微博 TimeLine)、消息队列(PUSH POP)
Set——集合 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
使用场景:共同好友、二度好友
Sorted Set——有序集合
使用场景:1.带有权重的元素,比如一个游戏的用户得分排行榜,比如队列普通消息与紧急消息的优先处理

https://www.jianshu.com/p/d645cebff386

--------------------------------------------过期策略 vs 内存淘汰机制---------------------------------------------
Redis中同时使用了惰性过期和定期过期两种过期策略
6种内存淘汰机制 通常用:allkeys-lru
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据

--------------------------------------------持久化--------------------------------------------
RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化) -- 牺牲数据完全(安全)性
容易恢复但不能避免数据丢失 因为数据是子进程定时写入临时文件的
AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件) -- 牺牲性能
更高的数据安全性,式清晰、易于理解的日志文件用于记录所有的修改操作可以通过该文件完成数据的重建,但AOF文件通常要大于RDB文件,恢复慢

--------------------------------------------分布式锁---------------------------------------------
1)Redis有很高的性能;
2)Redis命令对此支持较好,实现起来比较方便
相关命令:SETNX、expire、delete
获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个
随机生成的UUID,通过此在释放锁的时候进行判断。
获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放

1)Redis有很高的性能;
2)Redis命令对此支持较好,实现起来比较方便
相关命令:SETNX、expire、delete
获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个
随机生成的UUID,通过此在释放锁的时候进行判断。
获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放


==============================================================================================
13、熟悉 Linux 命令,
--------------------------------------------Linux---------------------------------------------
ps top tail
https://www.cnblogs.com/xuxinstyle/p/9609551.html

--------------------------------------------nginx,apache------------------------------------------
--Nginx
轻量级,采用 C 进行编写,同样的 web 服务,会占用更少的内存及资源
抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apache 高很多,而 apache 则是阻塞型的。在高并发下 nginx 能保持低资源低消耗高性能 ,
而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。
nginx 处理静态文件好,静态处理性能比 apache 高三倍以上
nginx 的设计高度模块化,编写模块相对简单
nginx 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂 ,重启的时候发现配置出错了,会很崩溃
nginx 作为负载均衡服务器,支持 7 层负载均衡
nginx 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器
启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,还能够不间断服务的情况下进行软件版本的升级
社区活跃,各种高性能模块出品迅速

--Apache
apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
apache 发展到现在,模块超多,基本想到的都可以找到
apache 更为成熟,少 bug ,nginx 的 bug 相对较多
apache 超稳定
apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区

总结
两者最核心的区别在于 apache 是同步多进程模型,一个连接对应一个进程,而 nginx 是异步的,多个连接(万级别)可以对应一个进程
一般来说,需要性能的 web 服务,用 nginx 。如果不需要性能只求稳定,更考虑 apache ,后者的各种功能模块实现得比前者,例如 ssl 的模块就比前者好,
可配置项多。epoll(freebsd 上是 kqueue ) 网络 IO 模型是 nginx 处理性能高的根本理由,但并不是所有的情况下都是 epoll 大获全胜的,如果本身提供静态服务的就只有寥寥几个文件,apache 的 select 模型或许比 epoll 更高性能。当然,这只是根据网络 IO 模型的原理作的一个假设,真正的应用还是需要实测了再说的。
更为通用的方案是,前端 nginx 抗并发,后端 apache 集群,配合起来会更好。






posted @ 2021-10-26 01:39  $wanggang  阅读(108)  评论(0编辑  收藏  举报