Tech Interview Essentials
Tech Interview Essentials
Programming Language
Go
goroutine的特点:空间小且可动态增长,函数前加go即可调度,GMP模型调度器
channel用来goroutine之间传递数据,类似于管道
返回error来决定是否成功
Interface可以用于定义对象的行为
空接口可以接受任何类型的值 interface{}
defer延迟执行函数
C++
new和malloc的区别:
项目 | new | malloc
类型 | 运算符(operator) | 函数(function)
功能 | 分配内存并调用构造函数 | 只分配内存,不调用构造函数
返回类型 | 返回正确类型指针(无需强转) | 返回 void*,需要强制类型转换
失败处理 | 抛出异常(std::bad_alloc) | 返回 NULL
释放方式 | 用 delete | 用 free()
智能指针 | 特点
std::unique_ptr | 独占所有权,不可拷贝,只能移动(move)
std::shared_ptr | 多个指针可以共享同一份资源,内部有引用计数
std::weak_ptr | 辅助 shared_ptr,不增加引用计数,防止循环引用(memory leak)
Singleton创建:懒汉式(需要时才创建),饿汉式(程序启动就创建),线程安全(mutex, call_once)
Computer Network
TCP/IP 四层网络模型:应用层,传输层,网络层,链路层。
OSI 七层网络模型:应用层,表示层,会话层,运输层,网络层,链路层,物理层。
MSS是TCP数据的最大长度 MTU是网络包(包含IP和TCP头部)的最大长度 ARP广播查询接收方MAC地址
根据URL查询对应IP
DNS查询:客户端,本地域名服务器(缓存),根域名服务器(.),顶级域名服务器(com),授权域名服务器(server.com)。
DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议。
浏览器流程:URL解析,TCP连接,HTTP请求,浏览器接收,页面渲染,断开连接。
Cookie存储在客户端,长时间保存少量数据,记录客户端状态;Session存储在服务端,短时间记录大量数据。
跨域:Nginx, CORS.
HTTP
先判断强制缓存,再决定是否请求协商缓存。
强制缓存:浏览器本地判断缓存是否过期,Cache-Control > Expires。
协商缓存:304,ETag > Last-Modified。
Status Code
- 100 提示
- 200 成功,204 已创建,206 部分返回
- 300 重定向,301 永久,302 临时,304 缓存返回
- 400 错误请求,403 权限禁止,404 未找到
- 500 服务器内部错误,501 尚未实施,503 服务不可用,504 网关超时。
GET是安全且幂等的,POST不是。
- HTTP/1.0 短链接,请求队头阻塞
- HTTP/1.1:无状态,明文传输,长连接,管道网络传输(发起多个请求),响应队头阻塞
HTTP1.0 队头阻塞,HTTP1.1 管道网络传输,HTTP2.0 header压缩+多路复用,HTTP3.0 QUIC(UDP)
HTTPS = HTTP + SSL/TLS, 安全性更高,消耗资源更多。(三个随机数client random, server random, pre-master验证) 安全性:混合加密(对称和非对称),摘要算法(哈希,公钥私钥),数字证书 HTTP's default port is 80; HTTPS's default port is 443.
TCP
TCP和UDP的区别:
- TCP要先请求建立连接,只能一对一
- TCP是可靠传输(校验和,seq序列号+ACK确认),确保数据有序且不会丢包
- TCP有拥塞控制和流量控制
- TCP按字节流传输,UDP按包传输
- TCP首部较长,在传输层分片;UDP首部短,在IP层分片
三次握手
保证双方都有发送和接收的能力
客户端向服务器发送SYN请求,服务器返回SYN+ACK,客户端返回ACK+Data。
原因:避免历史连接(网络遗留的请求),同步序列号。
SYN攻击:大量虚假客户端发送SYN请求,使得服务器的半连接队列爆满,使用Cookie。
四次挥手
客户端发送FIN等待服务器回复ACK,服务器处理完数据后发送FIN等待客户端回复ACK。
TIME-WAIT:2MSL(最大报文生存时间)
连接中客户端故障:TCP保活机制断开连接。
连接中服务端故障:仍然能四次挥手断开连接。
重传
- 超时重传
- 快速重传:收到三个相同的ACK时重传丢失的包
- SACK: 记录哪些已经收到,只重发未接收的包
- D-SACK:记录重复收到的包,可以让发送方知道具体原因。
滑动窗口
发送窗口大小由接收方的窗口大小决定(已发送但未收到确认+未发送但可以发送) 接收窗口(未收到但可以接收)
流量控制
让「发送方」根据「接收方」的实际接收能力控制发送的数据量
预防窗口关闭和糊涂窗口综合症
拥塞控制
拥塞窗口会由发送方根据网络的拥塞程度动态变化的。
- 慢启动:指数性增长。
- 拥塞避免算法:线性增长。
- 拥塞发生:重置为慢启动状态。
- 快速恢复:设置为原来的一半。
IP
IPv4地址32位,IPv6地址128位。简化了路由。
自动分配IP地址,随插随用;提高传输性能;安全性提高。
| 项目 | IPv4 | IPv6 |
|---|---|---|
| 地址长度 | 32 位(4 字节) | 128 位(16 字节) |
| 地址数量 | 约 42 亿个 | 接近无限 |
| 表示方式 | 点分十进制(如 192.168.0.1) | 冒号十六进制(如 2001:0db8::1) |
| 地址配置方式 | 手动配置 / DHCP | 自动配置(SLAAC)/ DHCPv6 |
| NAT 支持 | 广泛使用 NAT | 设计上不依赖 NAT |
| 安全性 | IPSec 可选 | IPSec 为协议内建部分 |
| 路由效率 | 路由表较大 | 简化地址结构,提升效率 |
| 广播方式 | 支持广播 | 不支持广播,使用组播和任播 |
| 报头复杂度 | 字段较多,处理相对复杂 | 报头简化,更利于硬件加速 |
Computer Operating System
用户态与内核态
ASCII只能表示英文字符,Unicode表示所有字符,UTF-8是一种与ASCII兼容的编码方案。
存储器
CPU寄存器,CPU Cache (L1, L2, L3(多核共享)),Memory内存,SSD/HDD硬盘
磁盘调度算法
- 先到先得:访问太分散
- 最短寻道时间优先 (Shortest Seek First):远距离磁道会产生饥饿
- 扫描算法 (Scan):磁头在一个方向上移动直至处理完所有请求,再转向另一方向扫描;中间磁道快于两端
- 循环扫描算法 (Circular Scan):磁头只在一个方向上处理请求,结束后快速移动回到复位起点
- Lock and C-Lock:不像Scan一样到达磁头尽头才返回,到达最远请求即可返回。
CPU
CPU 地址翻译,Virtual Page Number -> Physical Frame Number + Offset.
CPU 指令周期Pipeline: fetch, decode, execute, memory access, write back.
局部性原理:缓存加速内存访问。
CPU 缓存:L1,L2, L3(多核共享)
组织方式:直接映射缓存,全相联缓存,组相联缓存。
替换策略:随机替换,先进先出,最近最少使用(LRU),最不经常使用(LFU)
缓存一致性:通过MESI协议(Modified, Exclusive, Shared, Invalid)进行总线嗅探,广播进行写传播和写回操作。
增加CPU Cache利用率:(数据)访问连续地址;(指令)集中某一逻辑;(多核)线程限制在单核。
伪共享:多个线程同时读写同一个Cache Line的不同变量,导致cache失效;空间换时间。
调度任务
- 调度类:deadline, realtime(高优先级优先,先到先得,轮流进行), fair
- 安全公平调度:尽量分配给每个任务相同cpu,利用虚拟运行时间和优先级权重
- 运行队列:deadline > realtime > fair,红黑树排序
Memory
内存分段会导致内存碎片(不连续的空闲内存),内存交换效率低
内存分页和多级页表
Concurrency and Parallelism
并发Concurrency: 单核交替进行,async-await
并行Parallelism: 多核同时处理
互斥锁会进入阻塞状态,自旋锁会不断检查锁状态。
读写锁允许多个读线程,1个写线程。
共享锁=读锁,独占锁=写锁
- 互斥锁:失败后进入阻塞并切换线程;内核态来阻塞和唤醒,需要进行上下文切换,对短作业不友好
- 自旋锁:失败后忙等待并一直占用cpu;用户态切换请求,需要一直等待前面的作业
- 读写锁:读锁(共享锁),写锁(独占锁),读多写少;公平读写锁利用队列
- 悲观锁:以上三种都是,认为多线程同时修改资源的概率高,容易发生冲突
- 乐观锁:认为多线程同时修改资源的概率很低,不加锁,发生冲突时重试
死锁(Deadlock),互相等待对方持有的资源
条件:互斥条件,占有且等待条件,不可抢占条件,循环等待条件。
处理:破环一个死锁条件,检查资源分配情况;终止线程,回滚线程,动态资源分配,等待和重试。
Process and Thread
task_struct
协程(Coroutine): 用户态的轻量级线程,由程序代码直接实现,例如goroutine, async/await。
Process 进程
资源分配的基本单位,独立运行的程序实体。
状态:运行状态,就绪状态,阻塞状态(await),创建状态,结束状态,挂起状态(在硬盘等待)。
控制:创建,终止,阻塞,唤醒。
进程通信:
- 管道:单向通信;内核中的缓存,一端写入等待一端读出;匿名管道只能父子进程之间,命名管道可以跨进程
- 消息队列:内核中的消息链表,自定义,通信不及时,大小受限,用户态和内核态的数据拷贝开销
- 共享内存:拿出一段虚拟地址空间共享,映射到相同物理地址空间。
- 信号
- 信号量:保护共享资源;1互斥信号量,0同步信号量,P-1 V+1。
- Socket:跨网和本机内
Thread 线程
CPU调度的最小单位,进程内的一个执行流。
一个进程可以包含多个线程,线程之间可以并发,共享资源。
在C/C++中,一个线程崩溃会导致整个进程崩溃。
用户线程(切换快,操作系统无法干涉),内核线程(更多CPU时间,系统开销大)
对比:
- 进程是资源分配的单位,线程是 CPU 调度的单位
- 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈
- 线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系
- 线程能减少并发执行的时间和空间开销:创建快和终止快(无需管理资源),上下文切换快,数据交互效率高。
多线程冲突
竞争(race):多线程执行同一代码段,应该互斥
互斥:两线程不能在同一时刻执行,会竞争 (race)
同步:两线程需要保持先后顺序,合作
忙等待锁/自旋锁:获取不到锁就一直while等待占用CPU资源
无等待锁:获取不到锁就先调度其他线程。
信号量:资源的数量sem(保护共享资源);P操作-1,V操作+1(PV成对出现);1为互斥,0为同步;
生产者-消费者问题,哲学家就餐问题,
进程调度
调度原则:
- CPU利用率:发生I/O的进程要阻塞
- 系统吞吐量:权衡长任务和短任务的完成量
- 周转时间:(运行+等待)越短越好
- 等待时间:就绪队列的等待时间
- 响应时间:交互式较强的应该快
非抢占式调度算法:一个进程一直运行,除非主动阻塞或退出。
抢占式调度算法:根据时间片轮转反复切换进程。
调度算法:
- 先到先得 (First Come First Serve):对长作业以及CPU密集型作业有利,可能阻塞短任务。
- 最短作业优先 (Shortest Job First):对长作业很不利。
- 高响应比优先 (Highest Response Ratio Next):优先级= ,兼顾长短作业。
- 时间片轮转 (Round Robin):最古老、最简单、最公平、使用最广,20~50ms。
- 最高优先级 (Highest Priority First):静态,动态优先级(随时间状态调整);非抢占式(运行完当前再换),抢占式;低优先级永远无法运行。
- 多级反馈队列 (Multilevel Feedback Queue):兼顾处理长短作业。
- 多个队列优先级从高到低,优先级越高时间片越短;
- 优先级高的队列可以抢占调度,穷尽式优先;
- 未完成的进程会被放入下一级队列;
- 新进程会被放入第一队列末尾。
同步(Synchronous)需要等待返回结果才能进行下一步,异步(Asynchronous)在等待返回结果的同时可以继续执行其他操作。
阻塞(Blocking)需要调用者等待I/O数据,非阻塞(Non-blocking)可以立即返回一个错误码等待之后再次访问。
死锁
四个必要条件(全部满足才会发生死锁):
- 互斥:多个线程不能同时使用同一资源
- 占有且等待:等待其他资源时并不释放当前资源
- 不可强占用:不能抢占其他线程正在使用的资源
- 循环等待:获取资源的顺序构成了环
避免方法:使用资源有序分配法来破环循环等待条件,两线程获取资源的顺序一样。
File System
文件:索引节点 (index node,磁盘) 和目录项 (directory entry,内存)
硬盘分为超级块,索引节点区,数据块区
虚拟文件系统是对用户的统一接口。
基本操作单位是数据块,块组
目录存储采用哈希表
存储方式:
- 连续空间存放:读写效率很高,文件头需要指定起始块和长度;但是存在磁盘空间碎片和长度无法扩展的问题,类似于静态数组。
- 链表存放:离散不连续
- 隐式链表:文件头包含头尾指针,每个数据块存储next指针;只能按顺序访问,稳定性较差
- 显式链表:把每个数据块的指针存到内存的文件分配表中;检索速度快,但不适用于大磁盘
- 索引存放:单独存储索引数据块,支持随机访问;会造成存储开销
空闲空间管理:空闲表法(列表查询),空闲链表法,位图法(二进制记录,使用)
文件I/O:
- 缓冲和非缓冲(缓存一整行内容再输出)
- 直接和非直接(先访问内核缓存,再访问磁盘)
- 同步:阻塞和非阻塞,基于非阻塞的多路复用;异步 (aio_read)
使用DMA技术和sendfile实现零拷贝文件传输(Kafka)
PageCache:缓存最近被访问的数据,预读功能。
小文件使用零拷贝,大文件使用异步+直接。
Database (MySQL)
MySQL架构分为Server层和存储引擎层(InnoDB)
MySQL 8.0之后无查询缓存。
- 连接器:TCP握手,避免长连接填满内存(定期断开长连接,客户端主动重置连接)
- 解析器:提取关键字,构建语法树
- 执行:prepare, optimize, execute.
变长字段长度列表,NULL值列表,记录头信息(delete_mask, next_record, record_type)
关系的三个范式:每列的原子性,实体的唯一性,主键的依赖性。
Index
B+树是自平衡多路搜索树。只有叶子结点有数据,非叶子结点只有索引,叶子结点都在最后一层,用双向链表连接前后叶子。
B树的非叶子结点也存数据。B+树需要的磁盘IO次数少,且支持范围查询。
使用索引:主关键字,字段唯一约束,经常条件查询的,与其他表外键关联的,排序的,分组统计的。
主键索引:3-4次IO
二级索引:叶子结点存放主键值,查询两次B+树(回表)
联合索引:(a, b) 最左匹配原则
大于30%,全表扫描
索引优化:
- 索引下推:在联合索引遍历中,直接过滤非匹配记录,减少回表次数。
- 前缀索引:减小索引字段大小
- 覆盖索引:从二级索引中直接查询到所需数据,无需回表
- 主键索引自增:方便插入
- 索引 NOT NULL
Transaction
四大特性(ACID):
- Atomicity (原子性):一个事务中的操作,要么全部完成,要么全部回滚 -- undo log
- Consistency (一致性):数据库保持一致性,完整性状态
- Isolation (隔离性):并发事务相互隔离 -- MVCC, lock
- Durability (持久性):对数据的修改是永久的 -- redo log
并发事务的问题:
- dirty read 脏读:读到了其他事务已修改但未提交的数据,该数据可能回滚。
- non-repeatable read 不可重复读:前后两次读取的数据不一致由于其他事务的修改。
- phantom read 幻读:前后两次查询的行数量不一致由于其他事务的修改。
事务隔离级别:串行化(读写锁)> 可重复读(读取数据前后一致,默认)> 读已提交 > 读未提交
隔离级别越高,性能越低。
解决幻读的方法是快照读,当前读。
Lock
共享锁=读锁,独占锁=写锁
全局锁:数据库只读,全库备份;利用可重复读的read view来支持改写。
表级锁:
- 表锁:限制其他线程对本表读写,也限制本线程接下来只能读或写该表。
- 元数据锁:CRUD(MDL读锁),表结构变更(MDL写锁),写锁会阻塞读锁。
- 意向锁:意向共享锁和意向独占锁,快速判断表里是否有记录被加锁。
- AUTO-INC锁:保证主键自增连续,改用轻量级锁改善性能。
行级锁:
- Record Lock 记录锁:锁该条记录
- Gap Lock 间隙锁:解决可重复读隔离级别下的幻读,兼容不互斥。
- Next-Key Lock 临键锁:record lock + gap lock.
- 插入意向锁:插入事务被间隙锁的范围阻塞,等待锁。
死锁:访问资源顺序不同,试图插入间隙锁,自增主键冲突,索引未命中导致全表扫描,事务执行时间过长,大量并发更新。
解决方法:设置事务等待锁的超时时间,主动死锁检测。
Log
日志:undo log(回滚日志),redo log(重做日志),bin log(归档日志)
- undo log(回滚日志):原子性,回滚事务;MVCC多版本并发控制。
- redo log(重做日志):持久性,WAL 内存脏页的修改先记录下来,之后写入磁盘;事务宕机恢复;磁盘IO从随机写变为顺序写;循环写
- bin log(归档日志):server层,追加写,保存全量日志;主从复制
Buffer Pool 缓存查询或者修改过的数据,稍后写入磁盘。 redo log写入磁盘参数0(不主动写),1(写入磁盘),2(写入系统cache);每一秒InnoDB自动刷新。 两阶段提交要保证redo log和bin log的一致性
NoSQL
-
Massive read and write
-
Organizes data differently from tables and columns
-
No support for ACID transactions
-
Wide Column DBs,
-
Analytical DBs: by column, by sort
-
Document DBs: MongoDB; store whatever JSON data.
-
Full Text Search DBs: ElasticSearch (inverted index)
-
Graph DBs: nodes and edges
-
Vectors and Embeddings: LLM, recommendation.
Cache (Redis)
高性能高并发,基于内存操作,高效数据结构,I/O多路复用
主线程服务是单线程,但同时有后台多线程
不支持事务回滚
和Memcached的区别:支持的数据类型更多,数据持久化,事务等功能。
数据类型
- String (SDS): int, embstr, raw;直接保存JSON,或者每个属性分开存储;分布式锁,共享Session信息
- List (链表,压缩列表, quicklist, listpack):消息队列,保证顺序、全局ID避免重复消息、备份List留存
- Hash (链式哈希,rehash):哈希表对应;缓存对象
- Set (整数集):无序非重复,支持集合操作;共同关注
- ZSet (跳表):有序集合(score);实时排行榜
- BitMap, HyperLogLog, GEO
- Stream:消息队列,持久化,自动生成唯一ID,ACK确认,消费组模式
数据持久化
- AOF 日志:记录写操作命令以便写回;
- 写回策略:always, everysec, no(操作系统决定如何写回)
- 重写机制:文件过大时只保留最新记录,压缩文件大小;AOF重写缓冲区避免copy时update
- RDB 快照:记录某一瞬间的内存数据,直接覆盖
- 混合持久化:重写时,先记录RDB,再追加写时复制的AOF。
集群模式
主从复制
主支持读写,从只读,主会向从异步同步写操作;数据不一致
全量复制、基于长连接的命令传播、增量复制
- 主从建立链接,协商同步
- 主发送RDB,从全量复制
- 增量复制新写入数据,继续维护TCP长连接
从服务器下面可以继续划分从服务器
哨兵模式
监听主从服务器,如果主服务器挂了,会选举出一个新的leader作为主
哨兵集群(3个以上,通过发布订阅连接),通过多个主观下线判断出客观下线,然后发起leader投票(半数以上票,且大于等于quorum),这个leader来执行主从转移,quorum设置为哨兵数量的一半加1
主从转移:
- 选出新主节点:网络连接状态好,服务器优先级高,复制进度靠前,ID号小
- 将其他从节点指向新主节点
- 通知客户端主节点已更换,发送新IP和port
- 当旧主节点恢复时,设置为从节点
集群脑裂:主节点暂时失联,导致恢复后存在两个主节点,写操作冲突;禁止原主节点进行写操作并降级为从。
切片集群(cluster)
主从模式占用资源多,不好扩容。
把数据分布在多个服务器,通过哈希槽获取该访问哪个分片
节点之间通过Gossip协议通信(随机选择传播对象)
故障转移和哨兵模式相似。
删除策略
Redis是惰性删除+定期删除。 过期key删除策略:
- 定时删除:过期时会被定时器立即删除;浪费cpu
- 惰性删除:不主动删除,被访问时才会删除;cpu友好,内存不友好。
- 定期删除:定期随机检查并删除,删除率高时再循环一轮;减少无效内存占用,难以确定频率
持久化对过期键的处理:
- RDB:过期key不会被保存和加载,从无所谓
- AOF:写入时保留过期key,重写时忽略
- 从库不会检查过期key
内存淘汰:
- noeviction 不淘汰数据,禁止写入(default)
- allkeys-random, allkeys-lru, allkeys-lfu 所有数据范围内淘汰
- volatile-random, volatile-lru, volatile-lfu, volatile-ttl 设置了过期时间的数据中淘汰
- random: 随机淘汰
- LRU (Least Recently Used): 最久未使用的,记录最后一次访问时间,随机采样淘汰;缓存污染(最近访问大量低频数据)
- LFU (Least Frequently Used): 最少使用的,记录每个数据的访问次数
- TTL (Time-to-Live): 更早过期的
缓存设计
- 缓存雪崩:大量缓存数据在同一时间过期或Redis故障宕机;在原有过期时间基础上加上随机时间,互斥锁,后台更新缓存。
- 缓存击穿:某个热点数据过期;互斥锁保证同一时间只有一个线程访问缓存,后台更新热点缓存
- 缓存穿透:访问数据不在缓存和数据库中;限制非法请求,返回默认值,布隆过滤器。
缓存更新策略:Cache Aside(旁路缓存)先更新数据库,再删除缓存。
管道技术一次性处理多个请求
缓存模式对比
| 模式 | 描述 | 优劣 |
|---|---|---|
| Cache Aside | 读:未命中查 DB 并写缓存;写:更新 DB 后删除缓存 | 简单,更新一致性靠主动失效;需防击穿 |
| Read-Through | 应用写缓存层,由缓存层自动拉取 / 更新 DB | 透明,但可能隐藏复杂度;缓存宕机回源可能压力大 |
| Write-Through | 写操作先写缓存,再由缓存写 DB | 简化应用逻辑,但写延迟受缓存性能影响 |
| Write-Back | 写缓存后异步刷新 DB | 写性能极佳,但数据丢失风险高 |
Middlewares
同等条件下,kafka 吞吐量是每秒 17w ,rocketMQ 每秒 10w,而 RabbitMQ 则是 5w
ElasticSearch
基于Java+lucene
分布式,文档存储,搜索和分析,支持PB级数据,聚合查询(group by)
评分机制:BM25打分模型。
近实时(文档写入到可搜索有1秒延迟),集群, Index -> Type -> Document (db->table->row)
Segment:具备完整搜索功能的最小单元 (query and fetch)
- Inverted Index倒排索引:每个单词对应包含它的文档ID,Finite State Transducer
- Term Index:Trie优化单词索引
- Stored Fields:文档ID对应文档内容
- Doc Values:列式存储,排序和聚合
MeiliSearch
Rust,轻量级,支持docker,自动生成索引结构,支持typo容错
即时索引,几乎无延迟;支持排序和过滤;内置分页
不适合复杂聚合和海量数据,不支持分布式。
RabbitMQ
天然高并发 AMQP高级消息队列协议,消息确认ack
Exchange组件包含路由方式和绑定关系,分配放入队列
-
延迟队列(Delay):等待指定延迟时间后处理消息。订单超时处理。 TTL
-
死信队列(Dead Letter):处理失败后供后续排查和重新处理。 DLX
-
优先级队列
-
普通集群:Broker互相同步Exchange,不同步Queue;没有提升单个Queue读写能力
-
镜像队列集群:主从复制MQ(大部分仍在使用)
-
Quorum队列集群:主节点选举机制
Kafka
分布式流式处理平台:持久化消息队列,流数据处理;极致的性能,生态兼容性高
pull模式,消费者定时拉取消息。
- 高性能:把消息队列分成多个topic,一个消费者只能订阅一个topic;1个topic可以分为多个partition,每个消费者负责不同的部分
- 高扩展性:分布式机器
- 高吞吐:批量发送,零拷贝,页缓存优化。
- 高可用:主从复制备份
- 持久化:顺序写入磁盘,并添加过期删除策略
ZooKeeper监听每个broker
Nginx
支持动态配置多种通用网关能力和多种网络协议,单 master 多 worker 架构、多个worker进程之间共享内存和proxy cache,对外提供一个IP+端口,支持 http 服务器和反向代理的高性能网关服务
JWT (Json Web Token)
安全的传递声明信息(用户登录验证)
header(加密算法) + payload(数据信息) + signature(密钥签名)
特点:自包含,无状态,轻量级
Payload是明文可读的,不能存放敏感信息,JWT通过签名保证数据不被篡改
签发短有效期 Access Token + 长有效期 Refresh Token;每次用 Refresh Token 换新的 Access Token
Session
存储在服务端,可控制删除和失效,可记录更多上下文(最近操作)
多台服务器可扩展性:
- 中央化:把所有session存到同一个Redis集群上,所有后端服务器都从该Redis上拉取session
- 负载均衡粘性:配置Nginx,同一用户的请求始终转发到同一台服务器
- 会话复制:把session同步到各个服务器上