From 981641c57de003b4a1124a428271c40b046904b9 Mon Sep 17 00:00:00 2001 From: Ahern Date: Wed, 10 Apr 2024 19:03:30 +0800 Subject: [PATCH] feat: kubernetes and kafka --- _posts/2019-01-02-machine_units.md | 36 ++ _posts/2019-05-19-linux_command.md | 43 +++ _posts/2019-05-29-join_condition.md | 2 +- ...019-06-12-mysql_slow_query_optimiztion .md | 2 +- _posts/2019-08-11-linux_troubleshooting.md | 7 + _posts/2019-08-30-zero_copy.md | 46 +++ _posts/2019-10-10-process.md | 115 +++++++ _posts/2019-12-20-deadlock.md | 34 ++ _posts/2020-01-19-top_k.md | 33 ++ _posts/2020-02-20-hash.md | 20 ++ _posts/2020-03-02-sort.md | 44 +++ _posts/2020-03-18-intelligence.md | 9 + _posts/2020-05-09-redis.md | 170 ---------- _posts/2020-06-17-tree_and_table.md | 138 ++++++++ _posts/2021-01-09-io_model.md | 94 +++++ _posts/2021-04-16-mysql_mvcc.md | 57 ++++ _posts/2021-05-25-mysql.md | 321 ++++++++++++++++++ _posts/2021-09-11-postgre_sql.md | 72 ++++ _posts/2021-10-09-select_poll_epoll.md | 18 + _posts/2021-10-18-redis.md | 218 ++++++++++++ _posts/2021-10-25-redis_cluster.md | 88 +++++ _posts/2021-11-01-file_system.md | 17 + _posts/2022-01-11-ci.md | 102 ++++++ _posts/2022-03-28-k8s.md | 36 ++ _posts/2022-06-19-kafka.md | 113 ++++++ _posts/2022-08-18-scheduler.md | 41 +++ _posts/2022-09-10-nginx.md | 119 +++++++ _posts/2022-11-09-transaction_message .md | 78 +++++ 28 files changed, 1901 insertions(+), 172 deletions(-) create mode 100644 _posts/2019-01-02-machine_units.md create mode 100644 _posts/2019-05-19-linux_command.md create mode 100644 _posts/2019-08-30-zero_copy.md create mode 100644 _posts/2019-10-10-process.md create mode 100644 _posts/2019-12-20-deadlock.md create mode 100644 _posts/2020-01-19-top_k.md create mode 100644 _posts/2020-02-20-hash.md create mode 100644 _posts/2020-03-02-sort.md create mode 100644 _posts/2020-03-18-intelligence.md delete mode 100644 _posts/2020-05-09-redis.md create mode 100644 _posts/2020-06-17-tree_and_table.md create mode 100644 _posts/2021-01-09-io_model.md create mode 100644 _posts/2021-04-16-mysql_mvcc.md create mode 100644 _posts/2021-05-25-mysql.md create mode 100644 _posts/2021-09-11-postgre_sql.md create mode 100644 _posts/2021-10-09-select_poll_epoll.md create mode 100644 _posts/2021-10-18-redis.md create mode 100644 _posts/2021-10-25-redis_cluster.md create mode 100644 _posts/2021-11-01-file_system.md create mode 100644 _posts/2022-01-11-ci.md create mode 100644 _posts/2022-03-28-k8s.md create mode 100644 _posts/2022-06-19-kafka.md create mode 100644 _posts/2022-08-18-scheduler.md create mode 100644 _posts/2022-09-10-nginx.md create mode 100644 _posts/2022-11-09-transaction_message .md diff --git a/_posts/2019-01-02-machine_units.md b/_posts/2019-01-02-machine_units.md new file mode 100644 index 0000000..869f1d7 --- /dev/null +++ b/_posts/2019-01-02-machine_units.md @@ -0,0 +1,36 @@ +--- +title: 计算机单位换算 +date: 2019-01-02 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +### 位b(bit比特) +- 二进制位 + +### 字节B(byte) +- 1B = 8b + +### 字(word) +- 计算机进行数据处理时,一次存取、加工和传送的数据长度 +- 一个字通常由一个或多个(一般是字节的整数位)字节构成 +- 如:64位系统字的长度为64 + +### K +- 1K = 1024B = 2^10B 约 10^3B + +### M +- 1M = 1024K = 2^20B 约 10^6B + +### G +- 1G = 1024M = 2^30B 约 10^9B + +### logN +- 2为底 + +### lgN +- 10为底 + +### 1亿 +- 10^8 diff --git a/_posts/2019-05-19-linux_command.md b/_posts/2019-05-19-linux_command.md new file mode 100644 index 0000000..8f06b1a --- /dev/null +++ b/_posts/2019-05-19-linux_command.md @@ -0,0 +1,43 @@ +--- +title: 常用Linux命令 +date: 2019-05-19 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +### chmod + +- chmod 777 filename +- 编辑权限 +- r=4,w=2,x=1 + +### find + +- find pathname -options +- 查找文件 + +### ps + +- ps -ef +- 查看进程信息 + +### top + +- 动态查看进程cpu、内存等系统资源占用情况 + +### ping + +- 检测是否与主机ip连通 + +### telnet + +- 探测主机下某个端口是否开放 + +### vim + +### lsof + +- -i 查看端口占用 + +- -p [端口号]:查看进程占用的文件描述符 diff --git a/_posts/2019-05-29-join_condition.md b/_posts/2019-05-29-join_condition.md index ca98cd3..452863d 100644 --- a/_posts/2019-05-29-join_condition.md +++ b/_posts/2019-05-29-join_condition.md @@ -1,7 +1,7 @@ --- title: join接条件and、where区别 date: 2019-05-29 00:00:00 +0800 -categories: [root, mysql] +categories: [root, middleware] tags: [mysql] author: ahern --- diff --git a/_posts/2019-06-12-mysql_slow_query_optimiztion .md b/_posts/2019-06-12-mysql_slow_query_optimiztion .md index eb0280b..72ee496 100644 --- a/_posts/2019-06-12-mysql_slow_query_optimiztion .md +++ b/_posts/2019-06-12-mysql_slow_query_optimiztion .md @@ -1,7 +1,7 @@ --- title: Mysql慢查询优化 date: 2019-01-25 00:00:00 +0800 -categories: [root, mysql] +categories: [root, middleware] tags: [mysql] author: ahern --- diff --git a/_posts/2019-08-11-linux_troubleshooting.md b/_posts/2019-08-11-linux_troubleshooting.md index f454631..676342a 100644 --- a/_posts/2019-08-11-linux_troubleshooting.md +++ b/_posts/2019-08-11-linux_troubleshooting.md @@ -6,6 +6,12 @@ tags: [linux, troubleshooting] author: ahern --- +## 查看内存使用情况 +top、htop + +## 查看CPU使用情况 +top、htop + ## systemctl status查看service不断重启 #### 原因 服务发生Panic @@ -25,3 +31,4 @@ author: ahern - fdisk -l 查看分区 - df -lh 查看分区可使用占比 - du --block-size=MiB --max-depth=1 | sort -rn | head -10 查看当前目录最大的10个文件 +- `find ./ -type f -size "+50M" -exec du -h {} + | sort -rh|head -n 60` 查看大于50的文件,按大小倒序 diff --git a/_posts/2019-08-30-zero_copy.md b/_posts/2019-08-30-zero_copy.md new file mode 100644 index 0000000..7ea3c84 --- /dev/null +++ b/_posts/2019-08-30-zero_copy.md @@ -0,0 +1,46 @@ +--- +title: 零拷贝 +date: 2021-08-30 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +### 高速缓存PageCache + +- 在内存中有一个分区用来缓存热点数据 +- 有预读功能 +- 读写速度比磁盘快 +- 应用与内核态缓存区,如下文内核态缓存区 + +### DMA技术 + +- 在进行I/O设备(如:磁盘)和内存进行数据传输时,由DMA负责数据搬运,而不需要CPU参与 + +### 传统文件传输 + +- Snipaste_2022-02-18_14-51-45 +- 系统调用:read(file, tmp_buf, len)、write(socket, tmp_buf, len) +- 4次上下文切换:read两次+write两次 +- 4次数据拷贝:2次DMA拷贝 + 2次CPU拷贝 + +### 零拷贝技术 + +- Snipaste_2022-02-18_15-04-04 +- 零拷贝:数据传输过程中,**仅由DMA参与数据拷贝,CPU不参与** +- 系统调用:sendfile(int out_fd, int in_fd, off_t *offset, size_t count) +- 2次上下文切换:sendfile两次 +- 2次数据拷贝:2次DMA拷贝 + +### 大文件传输 + +- Snipaste_2022-02-18_15-12-30 +- 使用异步IO ,绕开PageCache,过程如图 +- 为什么不用零拷贝? + - 零拷贝使用了PageCache + - 很快占满PageCache,导致热点小数据不能使用PageCache + - 大文件PageCache命中率不高 + +### 参考 + +- 原来 8 张图,就可以搞懂「零拷贝」了:https://www.cnblogs.com/xiaolincoding/p/13719610.html diff --git a/_posts/2019-10-10-process.md b/_posts/2019-10-10-process.md new file mode 100644 index 0000000..99d419d --- /dev/null +++ b/_posts/2019-10-10-process.md @@ -0,0 +1,115 @@ +--- +title: 进程、线程、协程 +date: 2019-10-10 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +### 异常进程 +- 孤儿进程: + - 父进程退出,子进程仍在运行,子进程成了孤儿进程 + - 孤儿进程由init进程接管 + +- 僵尸进程: + - 子进程退出,父进程没有**wait或waitpid**,子进程描述还存在进程中,这个子进程就成了僵尸进程 + + +### 并发、并行 + +- 并发:一个CPU通过时间片轮询去调度多个程序,CPU同一时刻只能执行一个程序 +- 并行:多个CPU同一时刻执行多个程序,程序间互不抢占CPU资源。 + +### 进程、线程、协程 + +- 进程 + - 是操作系统资源分配的基本单元 + - 三种状态:就绪、运行、阻塞 + - 拥有独立的堆栈,进程间数据不共享 + - 场景:CPU密集型 +- 线程(go中没有直接创建线程的操作,go关键字创建的协程依赖于线程) + - 是CPU调度的基本单位 + - 存在于进程中,一个进程可以有多个线程 + - 共享堆空间、不共享栈空间 + - 由内核完成调度、上下文的切换 + - 场景:IO密集型 +- 协程 + - 用户基于线程去创建,由用户程序去实现调度 + - 共享堆空间、不共享栈空间 +- go协程 + - 本质上是协程,从语言层面上支持了协程 + - 独立的栈,用于保存其运行状态和局部变量 + - 共享堆,通过管道通信 + - 用户态,由GMP调度模型调度 + - 轻量级,开销小 + - go关键字创建 + +### 进程间通讯 +- 匿名管道 + + - 命令行"|" + - 父子进程间通信 + +- 命名管道 + + - 命令:mkfifo + - 两个进程间通信 + + ``` + 匿名、命名管道本质是在内核中一块缓冲区 + 优点:简单方便 + 缺点:随机进程生命周期结束而结束 + ``` + +- 消息队列 + + - 保存在内核中的消息链表 + - 优点:生命周期随核 + - 缺点:消息不及时 + - 缺点:用户态内核态频繁拷贝,效率低 + +- 共享内存 + + - 两个进程的一部分虚拟内存共同映射用一个块物理内存 + - 场景:键盘输入,打印进程打印 + + +- 信号量 + - **实现进程间互斥和同步,并不是实现进程间数据互通** + - 场景:值为1的互斥信号量 + - 场景:值为0的同步信号量 +- 信号 + - 异步通信机制 + - 如:kill +- socket + - 不同主机,进程间通信 + - 场景:TCP\UDP + +- 【参考】 + - https://www.cnblogs.com/xiaolincoding/p/13402297.html + + +### 线程分类 + +- 内核线程:存在于内核态 + - 处理器竞争:可以在全系统范围内竞争处理器资源。 + - 使用资源:内核栈和上下文切换时保持寄存器的空间 + - 调度:调度开销和进程差不多 +- 轻量级线程:抽象于内核线程之上,仅保留上下文信息,和调度程序所需要的统计信息 + - 处理器竞争:与特定的内核线程关联,可以在全系统范围内竞争处理器资源。 + - 使用资源:与父进程共享进程地址空间 + - 调度:由内核管理,像普通进程一样调度 +- 用户线程:由用户创建、调度、同步、销毁,不需要内核参与 + - 处理器竞争:线程间竞争所属进程的资源 + - 使用资源:与所属进程共享进程地址空间和系统资源 + - 调度:由进程实现调度 + +### 进程间切换与线程间切换的区别 +https://blog.csdn.net/xiangwanpeng/article/details/78196539?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-9-78196539.pc_agg_new_rank&utm_term=%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E6%80%8E%E4%B9%88%E5%88%87%E6%8D%A2&spm=1000.2123.3001.4430 +- 进程切换 + - 切换虚拟内存,切换页表 + - 刷新页表缓冲 +- 线程切换 + - 切换上下文,寄存器内容换出 +- 参考: + - https://blog.csdn.net/dan15188387481/article/details/49450491 diff --git a/_posts/2019-12-20-deadlock.md b/_posts/2019-12-20-deadlock.md new file mode 100644 index 0000000..75d495f --- /dev/null +++ b/_posts/2019-12-20-deadlock.md @@ -0,0 +1,34 @@ +--- +title: 死锁 +date: 2019-12-20 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +### 死锁四大条件 +- 互斥条件:资源在一个时间段内只能为一个进程使用,其他进程阻塞等待 +- 保持与请求条件:进程在保持占有一个资源,又请求新资源 +- 不可剥夺条件:进程占用的资源只能由该进程释放 +- 循环等待条件:多个进程形成循环等待资源释放 + +### 死锁处理方式(根据死锁产生的前中后) + +#### 预防死锁 +- 破坏死锁产生条件 + +#### 避免死锁 +- 银行家算法 +- 加锁顺序 +- 加锁时限 + +#### 检测死锁 +- 由操作系统实现死锁检测进程,若产生死锁,执行解除死锁 + +#### 解除死锁 +- 撤销进程法 +- 进程回退法 + +#### go死锁场景 +- goroutine无限阻塞chan +- mysql事务行锁导致死锁 diff --git a/_posts/2020-01-19-top_k.md b/_posts/2020-01-19-top_k.md new file mode 100644 index 0000000..4ff55cf --- /dev/null +++ b/_posts/2020-01-19-top_k.md @@ -0,0 +1,33 @@ +--- +title: 海量数据求top K问题 +date: 2020-01-19 00:00:00 +0800 +categories: [root, algorithm] +tags: [algorithm] +author: ahern +--- + +### 问题:海量数据求top K问题 +- https://blog.csdn.net/zyq522376829/article/details/47686867 +- 10亿个数中找出最大的10000个数 + +### 方式1:排序(快排) +- 时间复杂度:O(NlogN) +- 空间复杂度:O(NlogN) + +### 方式2:局部淘汰 +- 1、定义一个数组存储最大10000个数 +- 2、遍历10亿数,与最大数数组的最小数对比,大于则加入最大数数组 +- 时间复杂度:O(N + (M*N)) +- 空间复杂度:O(1) + +### 方式3:归并(分治) +- 1、10亿数据分成若干份 +- 2、找出每一个份的前10000个数,得100万个数 +- 3、对100万个数划分为二,分治 +- 时间复杂度:常数 + +### 方式4:最小堆 +- 1、10000个数建最小堆 +- 2、遍历剩下的数,和堆顶对比,比堆顶大则替换,重新建堆 +- 时间复杂度:O(Nmlogm) +- 空间复杂度:堆原地排序,O(1) diff --git a/_posts/2020-02-20-hash.md b/_posts/2020-02-20-hash.md new file mode 100644 index 0000000..e5432bd --- /dev/null +++ b/_posts/2020-02-20-hash.md @@ -0,0 +1,20 @@ +--- +title: 哈稀算法 +date: 2020-02-20 00:00:00 +0800 +categories: [root, algorithm] +tags: [algorithm] +author: ahern +--- + +## 哈稀算法 + +## 一致性哈稀算法 +- **尽可能少改变已存在的请求**与处理请求服务器之间的映射关系 +- 解决分布式系统中简单哈稀存在的动态伸缩问题 + +### 优点 +- 可扩展 + +### 缺点 +- 分布不均匀 + - 解决:虚拟节点,虚拟节点放在哈稀环,虚拟节点指向物理服务组 diff --git a/_posts/2020-03-02-sort.md b/_posts/2020-03-02-sort.md new file mode 100644 index 0000000..e23cfb3 --- /dev/null +++ b/_posts/2020-03-02-sort.md @@ -0,0 +1,44 @@ +--- +title: 排序算法 +date: 2020-03-02 00:00:00 +0800 +categories: [root, algorithm] +tags: [algorithm] +author: ahern +--- + +### 快速排序 +- 思想:分治 + - 1、选一个基准 + - 2、头、尾指针遍历,小于基准在左边,大于基准在右边 + - 3、递归基准的左边、右边 +- 时间复杂度:最好情况每次递归都平分数组,一共需要递归logn次,每次需要n时间,复杂度为O(n*logn),最坏情况每次都把数组分成1和n-1,一共需要递归n次,每次需要n时间,总体复杂度为O(n^2)。平均总体时间复杂度为O(nlogn)。 +- 空间复杂度:和时间复杂度相关,每次递归需要的空间是固定的,总体空间复杂度即为递归层数,因此平均/最好空间复杂度为O(logn),最坏空间复杂度为O(n) +- 稳定性:不稳定 +- 场景:小数据量排序 + +### 冒泡排序 +- 思想:双层遍历,逐个对比 + - 1、对比相临的数值,大者交换到后面 + - 2、重复对比 +- 时间复杂度:n^2 +- 空间复杂度:1 +- 稳定性:稳定 + +### 归并排序 +- 思想:分治 + - 1、递归对半分组,交换位置 + - 2、归并megre分组后结果 +- 时间复杂度:任何情况下为O(nlogn) +- 空间复杂度:n +- 稳定性:稳定 +- 场景:大数据量排序 + +### 堆排序(堆:完全二叉树) +- 思想: + - 1、构建堆,(升序构建最大堆,降序构建最小堆) + - 2、将堆顶元素下沉到数组尾部 + - 3、重新调整堆,重复下沉堆顶元素 +- 时间复杂度:O(nlogn) +- 空间复杂度:原地排序,O(1) +- 稳定性:不稳定 +- 场景: diff --git a/_posts/2020-03-18-intelligence.md b/_posts/2020-03-18-intelligence.md new file mode 100644 index 0000000..a44f4d0 --- /dev/null +++ b/_posts/2020-03-18-intelligence.md @@ -0,0 +1,9 @@ +--- +title: 智力题 +date: 2020-03-18 00:00:00 +0800 +categories: [root, algorithm] +tags: [algorithm] +author: ahern +--- + +https://www.nowcoder.com/discuss/526897 diff --git a/_posts/2020-05-09-redis.md b/_posts/2020-05-09-redis.md deleted file mode 100644 index c142c73..0000000 --- a/_posts/2020-05-09-redis.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Redis -date: 2021-01-30 00:00:00 +0800 -categories: [root, redis] -tags: [redis] -author: ahern ---- - -## 使用场景 -- 数值 -- 数据库记录(对象) -- 数据库查询语句 - - 语句采用hash算法 md5 -- 视图响应结果 -- 一个页面 - -## 过期策略 -- 定时过期:每个记录单独追踪有效期 - -- 惰性过期:只在查询数据的时候才判断数据是否过期 - -- 定期过期:每隔100ms 检查有哪些数据过期 - - **redis选用的过期策略为 惰性过期+定期过期** - -#### 内存淘汰策略 -- LRU(Least Recently Used) - - 以操作过的时间前后来选择淘汰 -- LFU(Least Frequently Used) - - 以操作的频率大小来选择淘汰 - - 定期衰减 ,所有使用次数减半 - -## 缓存模式 - -#### 缓存操作使用模式 - -- Cache Aside 缓存边缘 -- Read-through 通读 -- Write-through 通写 -- Write-behind caching 缓存之后写入 - - 更新操作只更新缓存,不更新数据库,由cache异步批量同步数据库。 - -#### 缓存数据更新方式 - -- 先更新数据库,在更新缓存 - - 问题:这种做法最大的问题就是两个并发的写操作导致脏数据 -- 先删缓存,在更新数据库 - - 问题:两个并发的读和写操作导致脏数据 -- 先更新数据库,再删除缓存 - - 问题:两个并发的读和写操作导致脏数据,数据库的写操作会比读操作慢得多,而且还要加锁,出现概率不大 - -#### 项目使用 - -- 使用Read-throught + Cache aside - - - 构建一层抽象出来的缓存操作层,负责数据库查询和Redis缓存存取,在Flask的视图逻辑中直接操作缓存层工具。 - -- 更新采用先更新数据库,再删除缓存 - - ```总结:读操作之后,才去设置缓存, - 总结: - 读操作之后,才去设置缓存, - 而写操作完mysql之后,一般不会修改缓存数据,而是删除缓存数据,等到下一次读操作的时候,才设置缓存 - ``` - -## 缓存问题 - -#### 缓存穿透 - -- 问题 - - 利用频繁去访问缓存中没有的数据,使缓存失去意义 -- 解决方法 - - 对于返回为NULL的依然缓存 - - 制定一些规则过滤一些不可能存在的数据,小数据用BitMap,大数据可以用布隆过滤器 - -#### 缓存雪崩 - -- 问题 - - 指缓存不可用或者大量缓存由于超时时间相同在同一时间段失效,大量请求直接访问数据库,数据库压力过大导致系统雪崩 -- 解决方法 - - 给缓存加上一定区间内的随机生效时间 - - 采用多级缓存,不同级别缓存设置的超时时间不同 - - 利用加锁或者队列方式避免过多请求同时对服务器进行读写操作(串行) - -## 持久存储 - -#### RDB快照持久化(默认开启) - -- 触发机制 - - - 定期触发 - - ```python - redis配置文件中: - save 900 1 # 900秒中有1次及以上修改到redis中数据 - save 300 10 # 300秒中有10次及以上修改到redis中数据 - save 60 10000 # 60秒中有10000次及以上修改到redis中数据 - ``` - - - 执行BGSAVE命令,手动触发RDB持久化 - - - SHUTDOWN命令,关闭redis时触发 - -#### AOF 追加文件持久化 - -- redis配置文件中: - - ``` - appendonly yes # 是否开启AOF - appendfilename "appendonly.aof" # AOF文件 - ``` - -- 触发机制 - - ```python - # appendfsync always # 执行每个命令都记录 - appendfsync everysec # 每秒记录 - # appendfsync no # 交给操作系统决定写到操作系统的时机 - ``` - -#### 总结 - -- redis允许我们同时使用两种机制,通常情况下我们会设置AOF机制为everysec 每秒写入,则最坏仅会丢失一秒内的数据。 - -## Redis高可用 - -#### Redis主从同步 - -- 客户端中通过命令 slaveof 主机地址 主机端口 来设置为从机 - -#### Redis哨兵机制 - -- 哨兵其实本身也是一个可执行程序,像我们启动redis客户端一样,只是它是用来看护redis实例进程的。 - -- 功能 - - Monitoring 监控 - - Notification 通知 - - Automatic failover 自动故障转移 - - Configuration provider 配置提供程序 -- 启动方式 - - redis-sentinel sentinel.conf - -## Redis集群 - -- 创建集群命令 -```python -redis-trib.rb create --replicas 1 192.168.192.200:7000 192.168.192.200:7001 192.168.192.200:7002 192.168.192.200:7003 192.168.192.200:7004 192.168.192.200:7005 -``` - -- 终端中连接到redis集群 - - `redis-cli -c -p 7000` - -- 代码中连接到redis集群 - - ```python - from rediscluster import StrictRedisCluster - # redis 集群 - REDIS_CLUSTER = [ - {'host': '127.0.0.1', 'port': '7000'}, - {'host': '127.0.0.1', 'port': '7001'}, - {'host': '127.0.0.1', 'port': '7002'}, - ] - - from rediscluster import StrictRedisCluster - redis_cluster = StrictRedisCluster(startup_nodes=REDIS_CLUSTER) - - # 可以将redis_cluster就当作普通的redis客户端使用 - redis_master.delete(key) - ``` diff --git a/_posts/2020-06-17-tree_and_table.md b/_posts/2020-06-17-tree_and_table.md new file mode 100644 index 0000000..46816fc --- /dev/null +++ b/_posts/2020-06-17-tree_and_table.md @@ -0,0 +1,138 @@ +--- +title: 树与表 +date: 2020-06-17 00:00:00 +0800 +categories: [root, algorithm] +tags: [algorithm] +author: ahern +--- + +### 节点的度 + +- 节点有几个分叉 + +### 高度 + +- 自底向上,叶子节点的高度为1 +- 树高logN + +### 深度 + +- 自顶向下,根节点的深度为1 + +### 二叉树 +- 定义: + - 任意节点的度不超过2 +- 查找时间复杂度:logN,递归深度logN;最坏情况下N +- 查找空间复杂度:logN,递归使用的栈空间;最坏情况下是N +- 遍历时间复杂度:N,每个节点都遍历 +- 遍历空间复杂度:N,递归使用的栈空间 + +### 完全二叉树 +- 叶子结点只能出现在最下层和次下层 +- 最下层的叶子结点集中在树的左部 +### 满二叉树 +- 任意一个节点都有两个孩子 + +### 二叉查找树 + +- 左子树小于根节点 +- 右子树大于根节点 +- 时间复杂度:O(logN),最坏时间复杂度O(N) +- 空间复杂度为 O(logN),,最坏时间复杂度O(N) + +### AVL树(平衡二叉树) +- 定义: + - 满足二叉查找树的基础上 + - 任意节点左右子树高度差(平衡因子)<=1 +- 优点: + - 查询效率稳定 +- 缺点: + - 维护平衡成本高 +- 应用场景: + - 插入少,查询多的场景 +- 时间复杂度:递归数的高度,O(logN),不会出现最差情况 +- 空间复杂度:为 O(logN),不会出现最差情况 + +### 红黑树 + +- 任意节点的左右子树的高度,相差不超过2 倍。 +- 树根是黑色 +- 叶子节点是黑色 +- 时间复杂度:O(logN) +- 空间复杂度为 O(logN) + + ![Snipaste_2022-02-11_16-10-06](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-11_16-10-06.png){:height="10%" width="50%"} + + - **保证较高的插入和删除效率** + - 优点: + - 不追求完全平衡,减少自旋 + - 兼顾删除和插入的效率 + - 缺点: + - 查询效率比平衡二叉树略低 + - 应用场景: + - 操作系统虚拟内存管理、hashmap键存储 + - epoll管理事件 + +### B树 + +- 任意节点左右子树高度差(平衡因子) == 0 +- 节点可以保存多个数据 +- 时间复杂度:O(logN) + + ![Snipaste_2022-02-11_15-59-59](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-11_15-59-59.png){:height="10%" width="50%"} + +### B+树 + +- 非叶子节点只保存索引,不保存数据 +- 叶子节点保存数据,并形成链表结构 +- 时间复杂度:O(logN) + +### Trie树(前缀树或字典树) + +- 根节点不包含字符,非根节点只包含一个字符 + +- 从根节点到某个节点,途经字符连起来就是该节点对应的字符串 + + ![Snipaste_2022-02-11_16-21-50](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-11_16-21-50.png){:height="10%" width="50%"} + + - 应用: + - 搜索引擎提示词 + - https://cloud.tencent.com/developer/article/1556054 + +### 跳表 +https://juejin.cn/post/6844903955831619597 + - 优点: + - 更新时,局部性更好 + - 支持范围查询 + - 缺点: + - 占空间 + - 应用场景: + - 内存多级页表 + - redis key管理 + - redis zset类型 + - 时间复杂度:近似二分查找,等于 索引高度:logn * 每层索引遍历元素的个数 = logn + - 空间复杂度:n/2(一级索引) + n/4(二级索引) + n/8(三级索引) + … + 8 + 4 + 2 = n-2,空间复杂度是 O(n) + ``` + redis中为啥用跳表而不用红黑树 + 1、更新时,跳表需要更新的范围更小,竞争锁的开销更小,并发高 + https://blog.csdn.net/qq9808/article/details/104865385 + ``` + +### 哈希表 + - 优点: + - 时间复杂度O(1) + - 缺点: + - 基于数组,扩充成本高,大数据量性能下降严重 + - 存在hash冲突 + - 不支持范围查询 + - 应用场景: + - map结构 + +### 区别(维度) +- 时间复杂度,空间复杂度 +- 是否有序 +- 可扩展性 + +### 参考: + +- https://jishuin.proginn.com/p/763bfbd2febb diff --git a/_posts/2021-01-09-io_model.md b/_posts/2021-01-09-io_model.md new file mode 100644 index 0000000..6da47f6 --- /dev/null +++ b/_posts/2021-01-09-io_model.md @@ -0,0 +1,94 @@ +--- +title: IO模型 +date: 2021-01-09 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +``` +1、同步、异步是相对于任务来说,即一个任务的处理,是否需要等待依赖任务的处理结果,才能继续向下执行;异步的消息通知采用回调的方式,而同步没有。 +2、阻塞、非阻塞相对于线程而言,即线程在调用结果返回之前,是挂起,还是继续处理其他任务,得到调用结果返回通知后继续执行。 +``` + +### 同步 + +- 一个任务的完成,需要等待所依赖任务的完成结果,才能继续向下执行。是一种可靠的任务序列 + +### 异步 + +- 一个任务的完成,不需要等待所依赖任务的完成结果,就可以继续向下执行。是一种不可靠的任务序列 + +### 阻塞 + +- 线程在调用结果返回之前,挂起,等到调用结果返回再继续执行 + +### 非阻塞 + +- 线程在调用结果返回之前,线程进行上下文切换,继续处理其他任务 + +### 同步阻塞 + +- 当前任务暂停执行,当前线程挂起 +- 效率最低 + +### 同步非阻塞 + +- 当前任务暂停执行,线程频繁上下文切换,监听依赖任务的结果 +- 上下文切换开销大 + +### 异步阻塞 + +- 当前任务暂停执行,依赖任务的结果回调通知。线程没有挂起。 +- 线程不是因为处理任务阻塞,而是因为等待消息阻塞 + +### 异步非阻塞 + +- 当前任务暂停执行,依赖任务的结果回调通知。 +- 当前线程通过上下文切换,去处理其他任务 +- 效率最高 + +# Linux五种IO模型 + +### 同步阻塞IO(blocking IO) + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210312140034.png) + +- 用户程序发起系统调用,线程挂起 +- 直到数据从内核复制到用户空间,并返回给用户程序 + +### 同步非阻塞IO(nonblocking IO) + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210312141124.png) + +- 用户程序发起系统调用,操作系统立即返回error,并开始准备数据 +- 用户程序并没有挂起,采用轮询的方式发起系统调用,检查内核数据是否准备好 + +### IO多路复用(IO multipleing) + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210312145415.png) + +- 多路:多个socket;复用:复用一个线程 +- select、poll、epoll函数可以实现多路复用 +- select阻塞用户程序,可以同时监听多个socket +- 任何一个socket的内核完成数据复制,就会通知用户程序到用户空间读取数据 + +### 信号驱动式IO + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210312150030.png) + +- 用户程序发起系统调用后立即返回 +- 系统内核准备好数据并复制到用户空间时,通过信号通知用户程序 +- 用户程序再调用recvfrom获取数据 + +### 异步非阻塞IO + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210312151623.png) + +- 用户程序提交系统调用后立即返回,用户进程可以去处理其他事情 +- 内核准备数据,复制到用户空间,并将数据交个用户进程 + +### 参考 + +- 同步、异步、阻塞、非阻塞:https://www.jianshu.com/p/aed6067eeac9 +- Linux IO模型:https://www.jianshu.com/p/486b0965c296 diff --git a/_posts/2021-04-16-mysql_mvcc.md b/_posts/2021-04-16-mysql_mvcc.md new file mode 100644 index 0000000..f7c2931 --- /dev/null +++ b/_posts/2021-04-16-mysql_mvcc.md @@ -0,0 +1,57 @@ +--- +title: MySQL MVCC +date: 2021-04-16 00:00:00 +0800 +categories: [root, middleware] +tags: [mysql] +author: ahern +--- + +### 是什么? +- Multiversion concurrency control (MCC or MVCC) +- 多版本并发控制(MCC 或 MVCC)是一种并发控制方法,通常被数据库管理系统用来提供对数据库的并发**访问(select)**,并以编程语言来实现事务存储。 + +### 解决了什么? +- 不加锁的情况下解决了脏读、不可重复读和快照读下的幻读问题(幻读问题最终就是使用间隙锁解决) + +### 如何实现? +- 隐式字段 + - DB_TRX_ID:记录改条数据修改它的事务 ID + - DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本 +- undo_log:日志版本链 +- read-view:执行select语句时生成的视图 + +### 当前读 +- 读操作加共享锁,写操作加排他锁 +- 场景: + - select...for update + - update , delete , insert +- 实现原理: + - 基于共享锁和排他锁 + +### 快照读 +- 普通的select操作,不加共享锁 +- 场景: + - select... +- 实现原理: + - undo_log + - MVCC + +### redo_log(恢复日志) +- 提高写操作效率 +- 保证事务持久性 +- 崩溃恢复(crash-safe) + +### undo_log(回滚日志) +- 事务回滚 +- MVCC + +### bin_log(二进制日志) +- 主从复制 +- 数据恢复 + +### 参考 +- *MVCC:听说有人好奇我的底层实现*:https://xie.infoq.cn/article/eff93ec47b54a5069e0bd1726 +- MySQL · 引擎特性 · InnoDB undo log 漫游 http://mysql.taobao.org/monthly/2015/04/01/ +- redo log和bin log https://blog.csdn.net/qq_40194399/article/details/120862971 +- MVCC多版本并发控制机制—包你学会 https://www.bianchengquan.com/article/231348.html +- 彻底搞懂MySQL的redo log,binlog,undo log:https://juejin.cn/post/6987557227074846733 diff --git a/_posts/2021-05-25-mysql.md b/_posts/2021-05-25-mysql.md new file mode 100644 index 0000000..a123c3f --- /dev/null +++ b/_posts/2021-05-25-mysql.md @@ -0,0 +1,321 @@ +--- +title: MySQL +date: 2021-05-25 00:00:00 +0800 +categories: [root, middleware] +tags: [mysql] +author: ahern +--- + +### 范式 + +- 1NF:原子性,列不可以再拆分。 + +- 2NF:1、表必须有主键。2、非主键列必须完全依赖主键,而不能只依赖主键的一部分。 + + - ``` + 例:订单明细表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。 + 因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的设计容易产生冗余数据。 + 可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。 + ``` + +- 3NF:在满足2NF的情况下,非主键列必须直接依赖主键,而不能依赖非主键类。也就是不能传递依赖。 + +- 反三范式:为了优化查询效率,可以增加冗余字段。 + +- 参考 + - https://thinkwon.blog.csdn.net/article/details/104778621 + - 三范式:https://blog.csdn.net/Dream_angel_Z/article/details/45175621 + +### 引擎 + +| | MyISAM | Innodb | +| :----: | :----------------------------------------------------------- | :----------------------------------------------------------- | +| 外键 | 不支持 | 支持 | +| 事务 | 不支持 | 支持 | +| 锁粒度 | 表级锁 | 行级锁、表级锁 | +| CURD | select更优 | insert、update、delete更优 | +| 索引 | 1、不支持哈希索引
2、支持全文索引
3、非聚簇索引
4、索引叶子节点存储的是行数据地址,需要再次寻址才能得到数据 | 1、支持哈希索引
2、不支持全文索引
3、聚簇索引
4、主键索引的叶子节点存储行数据,不需要再次寻址 | +| 场景 | 以读为主的应用程序,如博客、新闻 | 更新、删除频繁的应用,如op系统 | + +### 索引类型 + +- 主键索引 +- 普通索引 +- 唯一索引 +- 组合索引 +- 全文索引 + +### 主键索引、普通索引的区别 +- 主键索引B+树叶子节点存放整行数据,聚簇索引 +- 普通索引B+树叶子节点存放索引项-主键映射关系,需要回表查询,非聚簇索引 + +### 覆盖索引 +- 作用在联合索引 +- 直接在索引文件就可以读到数据,不需要回表查询 +- explain:extra列可以看到using index +- https://juejin.cn/post/6844903967365791752 + +### 聚簇索引、非聚簇索引 + +- 聚簇索引:数据和索引放在一起,找到了索引也就找到数据,不需要回表查询。如Innodb的主键索引 +- 非聚簇索引,数据和索引是分开的,索引结构只是保存了指向数据对应的行,需要回表查询。如MyISAM的B+tree索引结构 + +### 索引数据结构 + +- b+tree + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210204144458.png) + - 大多数情况下走的是b+tree索引 + - 非叶子节点不保存数据 + - 所有数据都保存在叶子节点 + - 叶子节点形成有序的列表结构,方便范围查询 + +- b-tree + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210204145443.png) + - 所有叶子节点都有保存key和数据 +- 为什么使用b+tree,而不是b-tree + - b+tree非叶子节点存储更多的元素,IO查询次数更少 + - 所有的查询都到叶子节点,性能更稳定 + - 叶子节点形成有序链表,便于范围查询 + +### 索引使用场景 + +- where +- order by +- join...on... + +### 索引使用方式 + +- 全值匹配最佳 +- 复合索引要遵从 最佳左前缀法则 +- 在索引列上操作(计算、函数、类型转换),引起索引失效 +- 范围查询(bettween//in)右边的列索引失效(当前列有效) +- select尽量覆盖索引列 +- is null、is not null、!=、<>、or 导致索引失效 +- like 以通配符开头('%字符串')导致索引失效 + +### 事务 + +- 是数据库操作的基本单位,要么都执行、要么都不执行 + +### 事务特性(ACID) + +- 原子性(Atomicity):是数据的执行单位,不可再分割,事务要么全部执行,要么全部失败;基于undo log实现 +- 一致性(Consistency):执行事务前后,数据保持一致,多个事务对同一个数据读取结果是相同的;通过回滚(undo log)、恢复(redo log)、锁、MVCC实现一致性 +- 隔离性(Isolation):事务之间互不干扰,并发事务之间各自独立;基于锁机制和MVCC使事务相互隔离 +- 持久性(Durability):事务提交之后,对数据库的改变是持久的;基于redo log日志持久化实现 + +### 脏读、不可重复读、幻读 + +- 脏读:一个事务读取了另一个事务未提交的数据 + +- 不可重复读:一个事务的两次读取同一分数据,两次的结果不一样,原因是在这两次读取之间,另一个事务对这份数据修改了 + +- 幻读(虚读):一个事务的两次读取一个范围内的数据,两次的结果不一样,原因是在这两次之间,另一个事务对这范围内的数据新增、删除了几行数据。 + + ```go + 1、不可重复读、幻读是读取了另一个已经提交了的事务,脏读是读取未提交的事务 + 2、不可重复读是针对一条数据,幻读是一批数据 + ``` + +### 事务隔离级别 + +- 读取未提交:允许读取未提交的事务,可导致**脏读** + +- 读取已提交:允许读取已提交的事务,可导致**不可重复读、幻读** + +- 可重复读:同一行数据多次读取的结果是一致的,可导致**幻读** + +- 串行化:最高隔离级别,所有事务依次执行,可**防止脏读、不可重复读、幻读** + + ```go + 1、事务隔离机制实现是基于锁和并发调度 + 2、MySQL默认隔离级别是可重复读 + 3、PostGreSQL默认隔离级别是读已提交 + ``` + +### 锁 + +- 事务并发情况下,锁实现了事务的执行次序 + +### 锁分类 + +- 功能分 + - 读锁(共享锁) + - 写锁(排他锁) +- 粒度分 + - 行锁: + - 页级锁: + - 表锁:MyISAM采用表锁 + +### 隔离级别和锁 + +- 读未提交:读取数据不需要加共享锁 +- 读已提交:读操作加共享锁,读语句执行完以后就释放共享锁 +- 可重复读:读操作加共享锁,读语句执行完以后不释放共享锁,事务结束后释放共享锁 +- 可串行化:事务加排他锁。 + +### 乐观锁、悲观锁 + +- 乐观锁:在需要修改数据之前,先查一下数据是否被修改过。一般是用版本号实现。适合读多写少的场景。 +- 悲观锁:基于数据库的锁机制。适合写多读少的场景。 + +### 间隙锁 + +- 加锁在空闲空间,可以是两索引之间,也可以第一个索引之前或最后一个索引之后 +- 防止幻读 + +### 优化 + +### 大表数据优化 + +- 优化表、SQL、加索引 +- 加缓存 +- 主从复制、读写分离 +- 垂直分表 +- 水平分表 + +### 超大分页处理 + +- 减少load的数据量 + + ```go + 【推荐】利用延迟关联或者子查询优化超多分页场景。 + + 说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。 + + 正例:先`select id from 表1 where 条件 LIMIT 100000,20 `快速定位需要获取的id段,然后再关联: + + SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id + ``` + +- 滚动加载,这样可以记录上一次的id, 用`where id >上一页的id` + +### 慢查询优化(重要) + +- 分析语句,是否load多余的行然后抛弃掉;是否查询了多余的列 +- explain分析执行计划,然后修改语句、修改索引 +- 表数据量太大,加缓存,分表,读写分离 + +### 主从复制 + +- 方式 + - 基于SQL(SBR) + - 优点:binlog比较小 + - 缺点:不是所有的update语句都被复制 + - 基于行复制(RBR) + - 优点:安全可靠 + - 缺点:binlog太大 + - 混合模式复制(MBR) +- 原理 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210207163522.png) + +- 主服务binlog线程把操作记录记录到binlog文件 + +- 从服务I/O线程把主服务的binlog同步到从服务中继日志 + +- 从服务的SQL执行线程读取中继日志,写入数据库 + + ``` + 1、两个日志 + 主:binlog日志 + 从:中继日志 + + 2、三个线程 + binlog线程:主,记录主服务的操作记录到binlog日志 + I/O线程:从,拉取主服务的binlog日志到中继日志 + SQL执行线程:从,执行中继日志,数据写入从服务 + ``` + +### 字符串的排序规则 + +- 基于字符集的排序 + +### 性能分析的命令方法 + +- show status 一些监控的变量值 + - Bytes_received/Bytes_send 服务器的来往流量 + - com_*:正在执行的命令 + - Created_*:在执行期间创建的临时表、文件 + - Select_*:不同类型的执行计划 +- show profile 是MySQL用来分析当前会话SQL语句的执行资源消耗情况 + +### 一条SQL语句在MySQL中的执行过程 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210314113322.jpg) +- 1、客户端通过TCP连接到服务端 +- 2、连接器做权限认证 +- 3、查询缓冲,命中则直接返回 +- 4、分析器做词法分析 +- 5、优化器确认执行计划 +- 6、执行器操作存储引擎 +- 7、存储引擎进行curd + +### MySQL基础架构 + +- 第一层:连接管理,授权认证,安全等 +- 第二层:编译和优化SQL +- 第三层:存储引擎 + +### count(*), count(1), count(列名) + +- count(*):包含所有列,统计结果是所有的行数 +- count(1):1表示忽略所有的列,统计的结果是所有的行数 +- count(列名):统计列名的那一列,统计的结果是该列值不为null的数量 + +### 触发器的类型 + +- Before Insert +- After Insert +- Before Update +- After Update +- Before Delete +- After Delete + +### 约束类型 + +- not null:不能为null +- unique:唯一约束 +- primary key:主键约束 +- foreign key:外键,级联删除等 +- check:用于控制字段的范围 + +### union与union all的区别 + +- union:对两个结果集进行并集操作,不包括重复行,同时进行排序 +- union all:对两个结果集进行并集处理,包括重复项 + +### SQL执行顺序 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210314134719.jpg) + +### expain的字段 + +- id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符. +- select_type: SELECT 查询的类型. +- table: 查询的是哪个表 +- partitions: 匹配的分区 +- type: join 类型 +- possible_keys: 此次查询中可能选用的索引 +- key: 此次查询中确切使用到的索引. +- ref: 哪个字段或常数与 key 一起被使用 +- rows: 显示此查询一共扫描了多少行. 这个是一个估计值. +- filtered: 表示此查询条件所过滤的数据的百分比 +- extra: 额外的信息 + +``` + 比较关注的字段:type、key、rows +``` + +### uuid性能低下的原因 + +- uuid无序,建立b+tree时效率低 +- uuid占用内存多,I/O效率低 +- 字符串连表性能差 + +### 参考 + +- MySQL索引背后的数据结构及算法原理:https://blog.codinglabs.org/articles/theory-of-mysql-index.html +- MySQL面试汇总:https://thinkwon.blog.csdn.net/article/details/104778621 +- 索引:https://blog.csdn.net/wuseyukui/article/details/72312574 + diff --git a/_posts/2021-09-11-postgre_sql.md b/_posts/2021-09-11-postgre_sql.md new file mode 100644 index 0000000..440fc9c --- /dev/null +++ b/_posts/2021-09-11-postgre_sql.md @@ -0,0 +1,72 @@ +--- +title: PostgreSQL +date: 2021-09-11 00:00:00 +0800 +categories: [root, middleware] +tags: [postgresql] +author: ahern +--- + +### 索引 + +- Btree、Hash、GIN、GiST、SP-GiST、BRIN +- `CREATE INDEX`默认是创建Btree索引 +- 主键默认建Btree索引 + +### Btree + +- Btree索引的实现类似MySQL的B+tree实现 +- 适用`< <= = >= >`、between、in、is null、is not null + +### Hash + +- 类似MySQL的Hash索引 +- 底层实现是哈希表 +- 只适用等值比较 + +### Gin + +- 是一种倒排索引 +- 存储的是键值对结构(key,posting list) + +### 正排索引、倒排索引 + +- 正排索引 + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210208111826.png) + - 文档id为关键字,文档内容为记录 + +- 倒排索引 + + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210208164256.png) + - 分词为关键字,文档id为记录 + +### json和jsonb + +- json + - 是对输入完整拷贝,保留了空格、键的顺序等 + - 使用的时候再去解析 + - 存储快,因为不需要解析,使用慢 + +- jsonb + + - 对输入进行解析成二进制后保存,不保留空格、键顺序等 + - 使用时不要再次解析 + - 存储慢,因为需要解析,使用快 + +- ``` + 两者的区别: + 1、存储,使用效率 + 2、空格、键顺序是否保留 + ``` + +- 可以在jsonb列上建gin索引 + +### 引擎 + +- heap +- 行级锁 + +### 参考 + +- gin索引:https://blog.csdn.net/ctypyb2002/article/details/108865908?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522161275168616780271587140%252522%25252C%252522scm%252522%25253A%25252220140713.130102334..%252522%25257D&request_id=161275168616780271587140&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-108865908.pc_search_result_before_js&utm_term=postgresql+gin + +- 官方文档:http://postgres.cn/docs/10/datatype-json.html#JSON-INDEXING diff --git a/_posts/2021-10-09-select_poll_epoll.md b/_posts/2021-10-09-select_poll_epoll.md new file mode 100644 index 0000000..026193e --- /dev/null +++ b/_posts/2021-10-09-select_poll_epoll.md @@ -0,0 +1,18 @@ +--- +title: select、poll、epoll之间的区别 +date: 2021-10-09 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +| | select | poll | epoll | +| ---------- | -------- | ------ | ---------------------------------------------------- | +| 数据结构 | 数组 | 链表 | 红黑树:存监听文件描述符
链表:存就绪文件描述符 | +| 获取fd方式 | 遍历 | 遍历 | 事件回调 | +| 时间复杂度 | O(n) | O(n) | O(1) | +| 数据拷贝 | 4次 | 4次 | 内存映射(mmap)3次 | +| 连接数 | 一般1024 | 无限制 | 无限制 | + + +参考:https://juejin.cn/post/6931543528971436046 diff --git a/_posts/2021-10-18-redis.md b/_posts/2021-10-18-redis.md new file mode 100644 index 0000000..0b453b8 --- /dev/null +++ b/_posts/2021-10-18-redis.md @@ -0,0 +1,218 @@ +--- +title: Redis +date: 2021-10-18 00:00:00 +0800 +categories: [root, middleware] +tags: [redis] +author: ahern +--- + +### 线程模型 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210319110526.png){:height="10%" width="50%"} + +### 数据类型 + +- string + + - ``` + struct sdshdr { + // buf 已占用长度 + int len; + // buf 剩余可用长度 + int free; + // 实际保存字符串数据的地方 + char buf[]; + }; + ``` + + - 获取字符串的长度复杂度为O(1) + + - 预分配内存,追加value是,先判断free空间,否则扩容 + + - 二进制安全,区别C字符串通过\0结尾 + + - 截断字符串时,先不释放free空间 + + - [动态字符](https://blog.csdn.net/u013318019/article/details/110691642?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161597393416780261959747%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161597393416780261959747&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-110691642.first_rank_v2_pc_rank_v29&utm_term=redis%E5%8A%A8%E6%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2) + +- hash + + - 哈希表 + +- set + + - intset + - 哈希表 + +- zset(有序集合) + + - 底层数据结构类型 + + - ziplist(压缩表):所有元素小于128,所有元素长度小于64 + + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210319102620.png){:height="10%" width="50%"} + + - **memeber和socore紧挨着** + + - skiplist(跳表):包括dict和zskiplist(方便范围查询) + + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210319103013.png){:height="10%" width="50%"} + - dict保存key/value + - zskiplist保存有序元素对象列表 + - 每个元素对象包含memeber、socore、level、回溯指针 + - dict、和zskiplist元素指向同一个位置 + +- 存储一个键的过程 + + - 查找key是否存在,不存在则创建 + - 若是ziplist:1、元素存在则删除后添加,超过限制则转为skiplist + - 若是skiplist:1、元素存在则删除后添加,在zskiplist中添加,然后更新dict + - 参考 + - https://www.jianshu.com/p/fb7547369655 + - 跳跃表:https://zhuanlan.zhihu.com/p/54869087 + +- list + +### 发布订阅 +- 命令 + - ![Snipaste_2022-02-24_14-34-56](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-24_14-34-56.png){:height="10%" width="50%"} + - publish:发布消息到channel + - subscribe:订阅一个channel + +- 实现原理 + + - ![Snipaste_2022-02-24_14-39-24](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-24_14-39-24.png){:height="10%" width="50%"} + + - redis以字典保存channel,键是channel,值为订阅该channel的链表 + + +### 持久化机制 + +- RDB:以固定的时间,将内存中的数据以快照的形式保存到硬盘中 + +- AOF:每个redis的命令请求,通过追加的方式保存到aof文件 + + ``` + 优缺点 + 1、AOF比RDB更新更频繁,aof文件更大 + 2、AOF安全型更好 + 3、RDB性能更好 + ``` + +### 过期键删除策略 + +- 定时过期:每个设置过期时间的 键 都会创建一个定时器,到了过期时间立即清除。这种方式对内存友好,耗CPU。 +- 定期过期:每隔一段时间就会扫描一定数量设置过期时间的 键。 +- 惰性过期:当访问 键 时,判断键是否过期,过期则删除。这种方式对CPU友好,但占内存。 + +### 内存淘汰策略 + +- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。默认策略 + +- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。 + +- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。 + +- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。 + +- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。 + +- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。 + + ``` + (重点) + LRU淘汰:最近最少使用(访问时间),该算法根据数据的历史访问记录进行淘汰。思想是“如果数据最近被访问过,那么将来被访问的几率也更高 + TTL淘汰:优先淘汰更快过期的键 + 随机淘汰:对redis中的键随机淘汰 + ``` + +### 事务 + +- multi(开启事务)、exec(执行事务)、discard(取消事务) +- 三个阶段:事务开始、命令入队、执行事务 +- 事务不支持回滚 +- 若一个事务中命令拼写错误`如:getk1`,则事务中的所有命令都不执行 +- 若一个事务中命令执行错误`如:incr k1,(k1的值为字符串)`,则事务中其他正确命令都执行 + +### lua脚本 + +- redis内部嵌入了lua脚本解释器 +- lua脚本的命令执行是原子性 + +### 管道 + +- 减少RTT,提高QPS +- 不是原子性 + +### 缓存异常 + +- 缓存雪崩 + + - 定义:缓存在同一时间大面积失效,请求直接访问数据库,数据库短时间内承受大量的请求而崩掉 + - 解决 + - 设置缓存过期时间为随机数 + - 设置多级缓存 + - 利用加锁或者队列方式避免过多请求同时对服务器进行读写操作(串行) + +- 缓存穿透 + + - 定义:指缓存和数据库**都没有**该数据,导致请求直接访问数据库,数据库短时间内承受大量请求而崩掉 + - 解决 + - 对应null值也做缓存 + + - 采用布隆过滤器,将所有可能存在的数据哈希到一个bitmap中,一定不存在的数据会被这个bitmap过滤掉 + + ``` + 随着数据库中的用户量增长,也去更新布隆过滤器 + ``` + + +- 缓存击穿 + + - 定义:缓存中**没有**但数据库中**有**的数据,大并发量的请求读取缓存没有读取到数据而访问数据库,导致数据库瞬间压力过大。 + + ``` + 和缓存雪崩不同的是,缓存击穿是指一条数据,缓存雪崩是指大批量数据缓存同时是过期 + ``` + + - 解决 + + - 热点数据永不过期 + +### 布隆过滤器 + +![Snipaste_2022-02-15_15-09-30](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-02-15_15-09-30.png){:height="10%" width="50%"} + +- 判断一个value一定不存在或者可能存在 +- 一个bit数组 + 三个hash函数 + +### 缓存更新方式 + +- 先更新数据库,再更新缓存 + - 若更新数据库成功,更新缓存失败,会导致脏读 +- 先删除缓存,在更新数据库 + - 假设更新操作先删除了缓存,此时正好有一个并发的读操作,没有命中缓存后从数据库中取出老数据并且更新回缓存,这个时候更新操作也完成了数据库更新。此时,数据库和缓存中的数据不一致,应用程序中读取的都是原来的数据(脏数据)。 +- 先更新数据库,在删除缓存 + - 推荐使用的方式,理论上还是可能存在问题 + - 写操作慢于读操作 + +### 版本新特性 + +- 6.0 + - 多线程IO(执行命令仍然是单线程) + - 1、IO 线程要么同时在读 socket,要么同时在写,不会同时读或写 + - 2、IO 线程只负责读写 socket 解析命令,不负责命令处理 + - 支持SSL +- 5.0 + - 新增流数据类型(stream data type) + - RDB可存储LFU和LRU +- 4.0 + - 新增LFU + +### 参考 + +- https://thinkwon.blog.csdn.net/article/details/103522351 +- 内存淘汰策略:https://www.jianshu.com/p/aa05f899aaf1 +- 缓存模式:https://blog.csdn.net/weixin_45439324/article/details/103372329 +- 布隆过滤器:https://www.cnblogs.com/heihaozi/p/12174478.html + diff --git a/_posts/2021-10-25-redis_cluster.md b/_posts/2021-10-25-redis_cluster.md new file mode 100644 index 0000000..777088c --- /dev/null +++ b/_posts/2021-10-25-redis_cluster.md @@ -0,0 +1,88 @@ +--- +title: Redis高可用 +date: 2021-10-25 00:00:00 +0800 +categories: [root, middleware] +tags: [redis] +author: ahern +--- + + +## 主从 +- 一主多从;主负责写,从负责读 +### 主从复制原理 + +![Snipaste_2022-03-25_10-40-40](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20220325104800.png){:height="10%" width="50%"} + +- 1、全量同步 +- 2、增量同步 + +### 优点 + +- 读写分离,提高并发 + +### 缺点 + +- 不具备容灾能力 + + +## 哨兵 + +### 总体架构 + +![Snipaste_2022-03-11_18-48-53](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-03-11_18-48-53.png){:height="10%" width="50%"} + +- 哨兵模式是Redis的高可用方式 +- 哨兵节点是特殊的redis服务,不提供读写功能 + +### 作用 +- 监控:监控redis node是否正常工作 +- 告警:redis出现故障,发出告警 +- 故障转移:自动选举新的master,并向客户端发布新的master配置 + +### 优点 + +- 读写分离 +- 自动故障转移 + +### 缺点 + +- 每台数据一致,内存使用率低 + +### 工作原理 + +- 1、心跳机制 + - Sentinel 向 Redis Node发送心跳包 + - Sentinel与Sentinel:基于发布订阅 +- 2、判断master节点是否下线 + - 主观下线:master回包异常 + - 客观下线:多数Sentinel判定成主观下线 +- 3、基于Raft算法选举领头sentinel +- 4、选举一个slave成为master + - 网络质量最好 + - 与master数据相似度最高 +- 5、修改配置 + - 领头sentinel向redis node广播新的master配置 + - 领头sentinel向客户端广播新的master配置 + +## 集群 + +![Snipaste_2022-03-25_11-17-11](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20220325111742.png){:height="10%" width="50%"} + +- 每个master节点存储的数据都不一样 +- client请求集群查找目标节点采用**slots 插槽**,不是一致性哈稀 + +### 工作原理 + +- 1、每个master节点,都有**slots 插槽** +- 2、存储key时,采用CRC16算法得出结果,对16384取模得到哈稀槽,根据哈稀槽找到master节点 +- 3、当masterA宕机,salveA会充当master;若masterA和salveA都宕机,集群不可用 + +### 优点 + +- 去中心话 +- 可线性扩展到1000多个节点,节点可动态添加或删除 + +### 缺点 + +- slave充当“冷备”,不能缓解读压力 +- 3.0推出,成功案例不多 diff --git a/_posts/2021-11-01-file_system.md b/_posts/2021-11-01-file_system.md new file mode 100644 index 0000000..28d4aca --- /dev/null +++ b/_posts/2021-11-01-file_system.md @@ -0,0 +1,17 @@ +--- +title: 文件系统 +date: 2021-10-09 00:00:00 +0800 +categories: [root, linux] +tags: [linux] +author: ahern +--- + +类型 + + - 普通文件:a.go + - 目录文件:/home + - 链接文件:不用目录下的文件共享 + - 设备文件:键盘、打印机 + - 命名管道:进程间通信 + +参考: https://thinkwon.blog.csdn.net/article/details/104588679 diff --git a/_posts/2022-01-11-ci.md b/_posts/2022-01-11-ci.md new file mode 100644 index 0000000..7002e16 --- /dev/null +++ b/_posts/2022-01-11-ci.md @@ -0,0 +1,102 @@ +--- +title: CI +date: 2022-01-11 00:00:00 +0800 +categories: [root, tools] +tags: [cicd] +author: ahern +--- + +### Pipeline +- commit/MR会触发pipeline执行 + +### Stages + +- Pipeline包含多个Stages +- 多个Stages依次执行 +- 包含多个流程,如:安装依赖、运行测试、编译、部署测试服务器、部署生产服务器 + +### Jobs + +- 一个Stages中包含多个Jods +- 多个Jods并行执行 + +### Runner + +- 用来执行构建任务 +- 一般把runner安装到其他机器 + +### 一个例子 + +```yaml +stages: + - install_deps + - test + - build + - deploy_test + - deploy_production + +cache: + key: ${CI_BUILD_REF_NAME} + paths: + - node_modules/ + - dist/ + + +# 安装依赖 +install_deps: + stage: install_deps + only: + - develop + - master + script: + - npm install + + +# 运行测试用例 +test: + stage: test + only: + - develop + - master + script: + - npm run test + + +# 编译 +build: + stage: build + only: + - develop + - master + script: + - npm run clean + - npm run build:client + - npm run build:server + + +# 部署测试服务器 +deploy_test: + stage: deploy_test + only: + - develop + script: + - pm2 delete app || true + - pm2 start app.js --name app + + +# 部署生产服务器 +deploy_production: + stage: deploy_production + only: + - master + script: + - bash scripts/deploy/deploy.sh + +``` + + + + + + + diff --git a/_posts/2022-03-28-k8s.md b/_posts/2022-03-28-k8s.md new file mode 100644 index 0000000..c2a1fd8 --- /dev/null +++ b/_posts/2022-03-28-k8s.md @@ -0,0 +1,36 @@ +--- +title: K8s +date: 2022-03-28 00:00:00 +0800 +categories: [root, middleware] +tags: [kubernetes] +author: ahern +--- + +### 架构体系 + +``` +k8s的master节点实现了对集群的管理,主要有四个组件:api-server、controller-mananger、kube-scheduler、etcd +``` + +- api-server:提供restful接口,实现整个k8s集群通信 +- controller_manager:集群的管理控制中心,对集群的资源进行管理 +- kube-scheduler:实现调度算法和策略,为pod选择合适的节点 +- etcd:非关系型数据库,集群内资源的存储 + +### 创建一个pod的流程 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210310100538.png) + +- api-server处理用户请求,将pod信息存储到etcd中 +- kube-scheduler预选和优选为pod选择最优的节点 +- 节点的kubelet从节点点中获取pod清单,下载镜像启动容器 + +### 参考 + +- 从零开始入门 K8s:详解 K8s 核心概念:https://www.infoq.cn/article/knmavdo3jxs3qpkqtzbw +- 官方文档:https://kubernetes.io/zh/docs/home/ +- https://www.jianshu.com/p/2de643caefc1 +- 学习路线:https://www.infoq.cn/article/9dtx*1i1z8hsxkdrpmhk +- minikube:https://github.com/kubernetes/minikube +- minikube docs:https://minikube.sigs.k8s.io/docs/start/ +- kubectl安装:https://github.com/caicloud/kube-ladder/blob/master/tutorials/lab1-installation.md diff --git a/_posts/2022-06-19-kafka.md b/_posts/2022-06-19-kafka.md new file mode 100644 index 0000000..dfde1dc --- /dev/null +++ b/_posts/2022-06-19-kafka.md @@ -0,0 +1,113 @@ +--- +title: Kafka +date: 2022-06-19 00:00:00 +0800 +categories: [root, middleware] +tags: [kafka] +author: ahern +--- + +### 总体架构 + +![649269d80d7b278699b49d3279511721](https://raw.githubusercontent.com/li-zeyuan/access/master/img/649269d80d7b278699b49d3279511721.png) + +- Producer:生成消息,push到Topic +- Broker:每个节点就是一个Broker,负责创建Topic,并将Topic中消息持久化到磁盘 +- Topic:同一个Topic可以分布在一个或多个Broker,一个Topic包含一个或多个Partition +- Partition:存储消息的单元,由Topic创建,分leader partition和follower partition +- Consumer:从订阅的Topic主动拉取消息并消费 +- ZooKeeper:维护集群节点状态信息 + +### Topic 与 Partition +- 分区策略:顺序分发、Hash分区 +- 每个Partition即是一个文件夹,包含.index、.log文件,读取消息时: + - 1、从.index文件获取消息在.log文件中的offset值 + - 2、从.log文件的offset位置开始读取消息 + - 3、消息定长,即到offset+len(消息定长)处结束读取 + +### 数据一致性 + +- ISR(in-sync Replica):与leader Broker数据保持**一定程度同步**的follower +- OSR:与leader Broker数据**滞后过多** 的follower +- LEO:每个broker消息偏移量 +- HW:所有broker的LEO最小值,Consumer只能读取HW之前的消息 + +producer生产消息至broker后,HW和LEO变化过程: + +- 1、Producer向broker发送消息 + + ![Snipaste_2021-11-19_11-18-33](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2021-11-19_11-18-33.png) + +- 2、Leader更新LEO,Follower开始同步Leader消息 + + ![Snipaste_2021-11-19_11-23-08](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2021-11-19_11-23-08.png) + +- 3、其中一个Follower完全同步了Leader的消息,另一个只同步了部分消息 + + ![Snipaste_2021-11-19_11-28-56](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2021-11-19_11-28-56.png) + +- 4、所有的Follower完成消息同步 + + ![Snipaste_2021-11-19_11-31-19](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2021-11-19_11-31-19.png) + +### 故障转移 +- 1、producer提交消息时,同步ISR中的一定数量的follower,才会回复ACK +- 2、ZooKeeper维护节点的alive状态 +- 3、leader节点宕机后,从ISR列表中选举一个follower节点成为leader + +### 可用性和持久性保证 +- 1、禁用unclean leader选举机制:ISR副本全部宕机情况下,不允许非ISR副本选举leader +- 2、指定最小的ISR集合大小,只有当ISR的大小大于最小值,分区才能接受写入操作 + +### 消费者组 +- 每个分区只能由同一个消费组内的一个consumer来消费 + + ![Snipaste_2022-03-24_18-21-29](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2022-03-24_18-21-29.png) + +### offset管理 +- 由消费者客户端提交 +- 早期放在Zookeeper,后来放在专用topic + +### Q&A +- 如何保证消息传输? + - broker commit成功,有副本机制(replication)的存在,保证消息不丢 + - broker commit不成功,producer会重试,可能导致重复消息 + +- 如何保证消息顺序? + - 同一个partition消息是有序的 + - 不同partition消息无序 + +- 为什么Producer不在Zookeeper中注册? + - Producer直接由Broker中的Coordinator协调、管理,并进行rebalance + - 减少Zookeeper的rebalance负担 + +- 如何保障Kafka吞吐率? + - partition顺序读写磁盘 + - broker持久化数据采用mmap页缓存 + - customer从broker读取数据采用0拷贝(sendfile) + - broker数据批处理,压缩,减少io,非强制刷新缓存写操作 + - customer并行读取partition消息 + - https://xie.infoq.cn/article/49bc80d683c373db93d017a99 +- 消费者获取消息是pull,而不使用push? + - 消费者根据自身的处理能力去拉取消息并处理,若采用push方式,可能会push消息速率过高而压垮消费者 + +- kafka怎么保证数据 一致性? + - 引入ISR、OSR、LEO、HW + - 既不是完全的同步复制,也不是单纯的异步复制,平衡吞吐量和确保消息不丢(**同步几个副本才会回复ack,可配置**) + +- 为什么不采用Quorum读写机制? + - Quorum:如果选择写入时候需要保证一定数量的副本写入成功,读取时需要保证读取一定数量的副本,读取和写入之间有重叠。 + - 优点:延迟取决与最快的节点 + - 优点:保证了读取和写入之间有重叠部分节点包含所有的数据 + - 缺点:多数的节点挂掉不能选择 leader + - 缺点:单点故障需要3份数据,要冗余2个故障需要5份,降低吞吐量,大数据量下成本高 + +- ZooKeeper高可用? + +- v2.8版本后移除ZooKeeper,采用KRaft方式 + - raft协议:https://xie.infoq.cn/article/57da6912139339e5098afb9cb + +### 参考 +- Kafka 详解:https://www.modb.pro/db/105106 +- 官文-设计思路:https://kafka.apachecn.org/documentation.html#design +- kafka为什么这么快:https://xie.infoq.cn/article/49bc80d683c373db93d017a99 +- Kafka 的基础架构:https://xie.infoq.cn/article/eabce320fb1d710db0e4fc9f9 diff --git a/_posts/2022-08-18-scheduler.md b/_posts/2022-08-18-scheduler.md new file mode 100644 index 0000000..9ee4767 --- /dev/null +++ b/_posts/2022-08-18-scheduler.md @@ -0,0 +1,41 @@ +--- +title: 定时任务的实现方案 +date: 2022-08-18 00:00:00 +0800 +categories: [root, linux] +tags: [scheduler] +author: ahern +--- + +### 1、PriorityBlockingQueue + Polling + +- PriorityBlockingQueue 为优先队列 + +- 生产者随机往队列中发送消息 + +- 消费者轮询获取消息并消费 + + ``` + 缺点:轮询的时间间隔不好控制,时间间隔太长,任务无法及时处理,间隔太短,消耗CPU + ``` + +### PriorityBlockingQueue + 时间差 + +- 生产者往队列中发送消息 + +- 消费者从队列尾部取出消息,计算时间差,然后sleep() + + ``` + 缺点:若队尾的元素的sleep时间过长,而队列中的消息的执行时间短,会导致队中消息不可被执行 + ``` + +### DelayQueue(延时消息) + +- 消费者向消息队列发送带有延时时间的消息 + +### 时间轮(HashedWheelTimer) + +![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210315164845.png) + +- 单位时间后,指针指向环形队列的下一个元素 +- 指针指向的位置,取出该位置的元素集合并执行 + diff --git a/_posts/2022-09-10-nginx.md b/_posts/2022-09-10-nginx.md new file mode 100644 index 0000000..c9e31b4 --- /dev/null +++ b/_posts/2022-09-10-nginx.md @@ -0,0 +1,119 @@ +--- +title: Kafka +date: 2022-09-10 00:00:00 +0800 +categories: [root, middleware] +tags: [nginx] +author: ahern +--- + +### 进程模型 + +- ![Snipaste_2021-08-03_11-26-43](https://raw.githubusercontent.com/li-zeyuan/access/master/img/Snipaste_2021-08-03_11-26-43.png) + +- master进程: + + - 接收来自外界信号 + - 向worker进程分发信号 + - 监控worker进程运行状态 + +- worker进程: + + - 连接accept后,读取请求、解析请求、处理请求 + + - 独立进程 ,一个请求只能被一个worker处理 + +- proxy cache + + - 缓存静态资源 + +### 工作流程 +##### 启动 +- ![v2-916b9832017683d98c248fde1717ac91_r](https://raw.githubusercontent.com/li-zeyuan/access/master/img/v2-916b9832017683d98c248fde1717ac91_r.jpeg) +- 启动进程启动后,fork出master进程后结束 +- master进程交给init进程接管 +- master进程worker出worker进程 +##### worker进程工作流程 + +- ![worker](https://raw.githubusercontent.com/li-zeyuan/access/master/img/worker.png) + + +### I/O模型 +- 通过epoll实现IO多路复用 +- 过程: + - 1、当一个请求accept时,worker调用epoll_ctl向epoll注册socket和回调事件 + - 2、继续监听\处理其他请求 + - 3、回调事件被触发,worker处理对应的socket + +### 信号管理 + +- ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/1468231-20190604222852999-553607453.png) + +### 惊群问题 +- what:当一个请求accept时,多个worker进程被唤醒去争夺处理权,请求被其中一个worker成功处理后,其他的worker又进入休眠,是一种资源浪费的现象 +- why: 因为多个worker监听同一个端口 +- resolve:nginx设置了一个accept_mutex锁 + +### 不停机更新配置 + +- 修改nginx.conf的配置 +- master节点会根据新配置fork出新的worker进程 +- 新的请求由新的worker进程处理 +- 等老的worker进程处理请求完成后会被kill + +### 为什么高效 + +- 多进程模型;采用多个worker 进程实现对 多cpu 的利用 +- 异步非阻塞;通过epoll实现IO多路复用机制 +- 事件模型;worker进程在处理request时,遇到阻塞,则向epoll注册一个事件,然后继续处理其他request。直到事件被触发,worker继续处理该request + +### 如何实现高可用 + +![v2-ec3208d1ea659d126fe2a008ec5ae927_r](https://raw.githubusercontent.com/li-zeyuan/access/master/img/v2-ec3208d1ea659d126fe2a008ec5ae927_r.jpeg) + +- Keepalived + 双机热备 +- 请求过来先落到keepalived,keepalived有虚拟ip(vip) +- keepalived通过心跳监控nginx的健康状态,然后做故障转移 +- 参考:https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247508995&idx=2&sn=9afa90512c951783982cec79a95ce6b1&chksm=96cee44fa1b96d59cd137d0f8b53cd55ddb814c4d7a45099f4290127d9659100006ba8a38d4c&scene=27#wechat_redirect + +### 限流 + +参考:https://www.cnblogs.com/Nicholas0707/p/12093173.html + +##### 漏桶算法 + +Snipaste_2021-09-16_17-35-23 + +- 请求从上方不定速进入 +- 请求从下方匀速流出 +- 超出桶容量,请求会被丢弃 + +##### 令牌桶算法 + +Snipaste_2021-09-16_17-35-23 + +- 令牌匀速生成,并放入令牌桶中 +- 请求到达时,获取令牌成功才能正常被处理 +- 获取令牌失败的请求将被缓存 + +##### 区别 + +- 令牌桶比漏桶多一个队列,用来缓存请求 +- 令牌桶(桶中令牌为最大值)允许突发流处理,令牌桶则限制请求的速度不超过设定的阀值 + +- Nginx请求限速模块采用的漏桶算法 + 令牌桶算法 + +##### 限制并发数:ngx_http_limit_conn_module + +- 限制客户端的IP并发连接数 + +##### 限制请求速率:ngx_http_limit_req_module + +- 限制请求处理速率 + +### 参考 + +- nginx 多进程 + io多路复用 实现高并发:https://zhuanlan.zhihu.com/p/346243441 +- nginx快速入门之基本原理篇:https://zhuanlan.zhihu.com/p/31196264 +- 模块和工作原理:https://cloud.tencent.com/developer/article/1664470?from=10680 +- 进程模型:https://cloud.tencent.com/developer/article/1664471 +- 7层网络以及5种Linux IO模型以及相应IO基础:https://www.cnblogs.com/jing99/p/11984966.html)https://www.cnblogs.com/jing99/p/11984966.html diff --git a/_posts/2022-11-09-transaction_message .md b/_posts/2022-11-09-transaction_message .md new file mode 100644 index 0000000..0e3f4c5 --- /dev/null +++ b/_posts/2022-11-09-transaction_message .md @@ -0,0 +1,78 @@ +--- +title: 事务消息 +date: 2022-11-09 00:00:00 +0800 +categories: [root, middleware] +tags: [rocket_mq, mms] +author: ahern +--- + +### 作用 + +- 解耦、异步、削峰。 + +### 模型 + +- 队列模型 + - 一对一共享消息 + - 消费者 拉取 消息的模式 +- 主题模型 + - 一对多广播消息 + +### 场景 + +- 消息顺序问题 + - 在项目中没有遇到需要处理消息顺序的问题 + - 在业务层控制顺序问题,不依赖MQ服务 + - 1、生产者生产消息,存到数据库中 + - 2、通知消费者 + - 3、消费者依次取出消息消费 + - 4、消费成功后,改变数据库中消息的状态 +- 消息重复问题 + - 消费者业务层实现幂等性,数据库记录消息的状态,重复消费直接返回 + +- 超大消息传输(消息体限制64k) + + - 1、生产者上传消息到oss + - 2、发送oss的下载链接到消息体 + - 3、消费者根据oss下载链接从oss下载消息 + - 参考 + - mns:https://help.aliyun.com/document_detail/34481.html?spm=a2c4g.11186623.6.620.2a107f59zczh0M + +- mns事务消息 + + - 事务消息队列:是业务消息的载体 + + - 操作日志队列:存放业务消息的确认状态,若超时未确认,则检查生产者事务结果,提交/回滚消息。作用类似RocketMQ**事务反查**的机制 + + - ![mns事务消息](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210202103059.png) + + - 1、发送准备消息(消费者不可见)到事务队列 + + - 2、发送消息写日志到操作日志队列 + + - 3、生产者执行事务操作 + + - 4、根据事务结果,提交/回滚消息 + + - 5、提交消息操作确认日志 + + - 6、7、8 消费者处理消息 + + ``` + 第4步出现异常,导致消息操作日志未确认 + 1、mns服务定期扫描超时未确认的操作日子 + 2、向生产者检查事务结果 + 3、提交/回滚消息 + 4、确认操作日志 + ``` + + - 参考 + - mns:https://help.aliyun.com/document_detail/34480.html?spm=a2c4g.11186623.6.621.7edd7f59PoDCcF + +- RocketMQ 事务消息 + + - ![](https://raw.githubusercontent.com/li-zeyuan/access/master/img/20210202110145.png) + - 其他步骤类似于mns的事务消息 + - 5、定期扫描超时未确认的事务消息,通过回调地址,检查本地事务状态,然后提交/回滚消息。 + - 参考 + - https://juejin.cn/post/6844904106532962311