- 博客(36)
- 收藏
- 关注
原创 计算机网络 —— TCP/IP
本文主要探讨了学习网络协议的重要性及核心内容。文章首先分析了日常开发中常见的网络问题(如接口超时、连接断开等),指出这些问题背后都涉及网络协议知识。随后介绍了网络协议的分层思想,对比了OSI七层模型和TCP/IP四层模型。重点解析了TCP/IP协议栈中的IP协议、路由机制、TCP可靠传输机制(三次握手/四次挥手、流量控制、拥塞控制)以及UDP协议特点。通过实际抓包案例,详细说明了DNS查询、TCP连接建立、数据传输和连接关闭的全过程。最后对比了TCP和UDP的特性差异及适用场景,帮助开发者根据具体需求选择合
2026-07-10 17:23:46
280
原创 操作系统内存管理 —— 虚拟内存
本文深入探讨了虚拟内存的核心机制及其实现原理。首先分析了传统内存管理的局限性(碎片化、进程隔离、程序大小受限),引出虚拟内存的解决方案。文章系统阐述了虚拟内存的三大关键技术:请求分页管理(通过扩展页表实现按需调页)、页面置换算法(包括OPT、FIFO、LRU、CLOCK等)、页面分配策略(固定/可变分配与全局/局部置换的组合)。特别强调了工作集模型对防止系统抖动的重要性,并对比了内存映射文件与传统I/O的性能差异。文章技术细节丰富,涵盖了从硬件支持(MMU/TLB)到操作系统实现(缺页处理、置换策略)的完整
2026-07-08 19:55:15
304
原创 带着问题去探险:亲手“设计”出 Ceph BlueStore
我们有一块普通的硬盘,想在上面存 Ceph 的对象(比如一张图片)。操作系统教我们:先格式化一个文件系统(比如 XFS),然后open一个文件,把数据write进去。灵魂拷问 1直接用操作系统的文件系统存数据,有什么不对吗?在早期的ceph(FileStore时代),我们就是这么干的。但运行久了,发现了几个及其别扭的“拧巴”现象:拧巴点一:写 4KB 数据,磁盘写了两次。拧巴点二:修改文件中间的1个字,硬盘忙半天。
2026-07-05 15:41:37
389
原创 从 Paxos 到 Raft 再到 CRUSH:分布式系统三种核心算法的设计哲学
本文系统分析了分布式系统中的三种核心算法:Paxos、Raft和CRUSH。Paxos作为理论基石,通过两阶段提交实现分布式共识,但存在理解困难和工程实现复杂的问题。Raft在Paxos基础上优化,引入强领导者、明确选举机制和日志连续性设计,大幅提升了可理解性和工程落地性。CRUSH则专注于数据分布问题,通过层次化故障域和智能哈希算法实现去中心化的数据放置。三者各司其职:Paxos/Raft解决一致性问题,CRUSH解决数据定位问题,共同构建完整的分布式系统架构。文章深入剖析了各算法的设计思想、工作机制和优
2026-06-30 15:15:21
319
原创 初识ceph:统一存储的“三头六臂”
存储处理能力不足:传统的IDE的io值是100次/秒,SATA固态磁盘500次/秒,NVMe固态硬盘达到2000-4000次/秒。即使磁盘的io能力再大数十倍,难道能够抗住网站访问高峰期数十万、数百万甚至上亿用户的同时访问么?这还收到网络io能力的限制存储空间不足:单块磁盘容量再大,也无法满足用户正常访问所需的数据容量限制。需求可以横向扩展存储系统,这种存储系统的表现方式有很多,不过他们有一个统一称呼—— 分布式文件系统DFS = Distributed File System,分布式文件系统。
2026-06-26 17:13:16
344
原创 深入解析 Go 网络 I/O 的底层引擎:从 epoll 到 netpoll
epoll 负责感知 I/O 就绪(fd 级、内核级),netpoll 负责把就绪翻译成"哪个 G 可以恢复了"(G 级),GMP 负责真正把那个 G 调度到 CPU 上跑——
2026-06-13 18:07:03
437
原创 GMP生态价值:不止是调度器,而是Go并发世界的“宪法“
模块它依赖GMP的什么结构?怎么体现"统一秩序"调度器G/M/P状态机 + 队列体系g的一生(创建→就绪→运行→等待→死亡)全程由GMP管理内存管理P作为稳定上下文 → mcache绑P每个g通过当前P无锁拿内存,分配语义与调度语义一致并发原语gopark/goready操作g状态+队列channel/mutex/timer全以g为单位挂起/唤醒,绝不升到thread网络I/Onetpoll把epoll事件翻译为goreadyIO就绪汇入同一套就绪队列,等待中的g不占M。
2026-06-09 14:59:08
226
原创 Go语言GMP调度模型深度解析:高并发背后的精妙设计
本文深入解析Go语言GMP调度模型的核心原理与实现机制。文章首先对比传统线程模型与协程的优劣,指出线程在高并发场景下存在资源消耗大、上下文切换成本高等问题。随后详细阐述GMP三大组件:Goroutine(轻量级协程)、Machine(线程抽象)和Processor(调度中枢)的协同工作机制,通过M:N绑定关系实现高效并发。重点分析四级调度策略(本地/全局队列、I/O唤醒、工作窃取)和让渡机制(正常结束、主动让渡、阻塞让渡),并探讨系统调用抢占与运行超时抢占(包含协作式和异步信号抢占)的实现细节。最后总结GM
2026-06-08 22:06:37
393
原创 Go内存模型与GC机制:高性能编程的核心
逃逸分析是Go编译器在编译阶段执行的静态分析,用于确定变量的生命周期和分配位置。逃逸分析的目标确定变量是否超出函数作用域决定在栈还是堆上分配优化内存分配,减少GC压力。
2026-05-31 19:45:09
291
原创 事务的进化:从MySQL单机事务到TiDB分布式事务的探究
在单机时代,MySQL通过集中的锁管理、本地事务ID和Undo日志,在单一服务器内高效实现了事务ACID。然而,其扩展性受限于单点硬件。为突破此瓶颈,TiDB等分布式数据库采用全新架构。其核心是Percolator模型:它引入全局时间戳定序,通过两阶段提交和随机选定Primary Key来协调跨节点事务,并将锁与状态分散存储在数据中,实现了去中心化的自我修复。这标志着从事务“集中控制”到“协同工作”的根本转变,以引入网络开销为代价,换取了无限的水平扩展能力。
2026-05-29 11:07:09
424
原创 纸上得来终觉浅?从 0 到 1 实现分布式 KV 后,我才读懂了 TiDB 的设计
作者从零实现了基于 Raft 的分布式 KV 存储系统(JLDB),并将其与工业级标杆 TiKV 进行深度对比。本文围绕架构设计、分片机制、存储引擎、读写优化等核心维度,剖析了两者的异同,揭示了从“正确的实现”到“工业级稳健”的思维跃迁。通过这一对比,作者不仅加深了对分布式系统设计权衡的理解,也明确了后续优化 JLDB 的方向。本文适合正在学习分布式存储、Raft 共识算法或 TiDB 技术栈的读者阅读。
2026-05-24 17:15:43
430
原创 从存储引擎到文件系统:用FUSE将分布式KV挂载为本地目录
本文介绍了一个基于FUSE框架实现的分布式文件系统,该系统通过用户态文件系统与分布式KV存储相结合,实现了基本的文件操作功能。系统采用TCP/IP通信和RESP协议与分布式KV存储交互,核心功能包括文件读写、属性获取、目录列表等。文章详细阐述了网络通信模块、KV操作封装和FUSE文件系统操作的实现原理,同时也指出了当前系统在文件大小限制、并发控制和目录支持等方面的局限性,并提出了改进方向。该项目主要用于学习和理解FUSE框架的工作原理。
2026-05-23 17:10:29
489
原创 探究raft的线性一致性读方法
本文探讨了分布式系统中实现线性一致性读的优化方法,重点分析了Raft算法的LeaseRead机制及其改进方案。线性一致性作为最强的一致性模型,要求系统表现得像单机系统,但传统Read-as-Write方法存在性能问题。LeaseRead通过心跳维护租约期,允许Leader直接读取本地状态机,但存在时钟漂移风险。文章详细介绍了LeaseRead的实现流程,包括租约状态管理、心跳更新机制和客户端读请求处理,并提出了三种优化方案:使用单调时钟、基于心跳计数器的Lease以及ReadIndex回退机制。最后对比了e
2026-05-22 16:57:23
420
原创 gRPC DeadlineExceeded 问题分析与总结
本文分析了基于Raft算法的分布式数据库在高并发场景下出现的gRPC超时问题。主要原因是200ms的RPC超时设置不合理,导致Follower日志跟不上Leader。作者尝试了多种优化方案:1) 批量异步持久化(违反Raft安全性);2) 同步批量持久化(批量效果不佳);3) 同步非批量持久化;4) 减小锁粒度(有效减少超时);5) 流水线复制(最佳方案)。最终发现减小锁持有时间和采用流水线复制是解决RPC超时的有效方法,既保证了安全性又提高了性能。文章详细记录了每种方案的测试结果和权衡过程,为分布式系统性
2026-05-11 15:05:14
367
原创 自研基于Raft的高性能分布式KV存储系统(一)
目前市面上有很多成熟的数据库产品,如redis、mysql、memcached、rockdb等。数据库(Database)的主要作用是存储、管理和检索数据,以支持各种应用和系统的正常运行。它通常作为一个中间件而存在,是一个独立的进程可用于使用网络连接进行访问。而数据库又可以分为磁盘型数据库和内存行数据库。特性磁盘数据库内存数据库存储位置磁盘(硬盘/SSD)内存(RAM)速度较慢(受磁盘IO限制)极快持久性高(数据存储在磁盘)需特殊配置(支持持久化)或易丢失数据容量大(受硬盘限制)
2026-03-06 15:15:28
609
原创 linux进程调度
CFS是Linux默认的普通进程调度器,其核心思想是完全公平。它摒弃了传统时间片,引入了虚拟运行时间的概念。每个进程的虚拟运行时间会根据其优先级(nice值)进行加权计算。CFS通过一颗红黑树来组织所有可运行进程,树的键值就是虚拟运行时间。调度时,它总是选择虚拟运行时间最小的进程来运行。这样,高优先级进程的虚拟时间增长慢,更容易被频繁调度,从而获得了更多的CPU时间;同时,经常睡眠的交互式进程也能快速得到响应,保证了系统的公平性和交互体验。
2025-11-03 15:37:54
891
原创 自研基于Raft的高性能分布式KV存储系统(二)
在作者看来,想要提高大规模的数据的读写性能可以从以下两个方面进行入手:更好的机器:属于纵向扩展,在系统设计上没什么工作量,但压力来到了硬件设计这一侧。机器的性能达到一定程度之后,想要更进一步的梯度会陡然提升。更多的机器:属于横向的扩展,如果在网络环境绝对理想的情况下,这种方式可以做到上不封顶。设立更多的机器,既可以在系统安全性方面做到状态数据的容灾备份,也能够在处理请求流程中通过负载均衡的方式减轻单个节点的压力从而提高系统的整体上限当然,在现实中并没有绝对理想。
2025-10-13 13:30:22
393
原创 初识Docker
docker容器在产生数据的时候,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除之后,数据自然而然的也会消失。为了能保存数据,容器中引用了数据卷的概念。Dockerfile是一个创建镜像所有命令的文本文件,包含了一条条指令和说明, 每条指令构建一层,,通过docker build命令,根据Dockerfile的内容构建镜像,因此每一条指令的内容, 就是描述该层如何构建。
2025-07-13 16:28:49
922
原创 gRPC使用
RPC 即远程过程调用协议(Remote Procedure Call Protocol),可以让我们像调用本地对象一样发起远程调用。RPC 凭借其强大的治理功能,成为解决分布式系统通信问题的一大利器。解决了单体架构的弊端,但同时引入了新的问题服务拆分后,服务和服务之间发生的是之间的调用,之间的调用,那么就需要发起网络调用。网络调用我们能立马想起的就是http,但是在微服务架构中,http虽然便捷方便,但性能较低。这时候就需要引入RPC(远程过程调用),通过自定义协议发起TCP调用,来加快传输效率。
2025-05-26 16:18:27
980
原创 Golang —— channel
在go语言中的goroutine是可以支持高并发操作的,而且go语言对高并发支持做的是非常好的一种语言,线程与线程之间或者协程与协程之间实现如果需要实现并发,那么不可或缺的就是需要进行通信,那么go语言协程间如何实现高性能通信的呢?——Channel。Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯。go语言中有一种很经典的说法,我们如何理解上面这段话呢?其实我们知道在内核视角下,线程是内核调度的最小单位。
2025-05-10 21:23:09
880
原创 Nginx 代理与conf文件
Nginx(发音类似“Engine-X”)是一款高性能的开源网页服务器和反向代理服务器,最初由俄罗斯程序员Igor Sysoev开发,现广泛应用于各种网站和应用的服务器端。是一款用于搭建网站、实现请求转发和负载均衡的高效Web服务器,因其速度快、占用资源少和扩展性强而广受欢迎。
2025-05-07 15:01:32
1000
原创 Golang —— Slice
Go 语言切片是对数组的抽象。Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。切片中的元素存放在一块内存地址连续的区域,使用索引可以快速检索到指定位置的元素;切片长度和容量是可变的,在使用过程中可以根据需要进行扩容。
2025-05-01 14:48:33
1234
原创 go语言实现raft —— PartD
空间不够:如果日志无限追加下去,本地硬盘空间可能存储不下重启过慢:因为重启需要重发(replay)所有日志,如果日志过长,重放过程将会持续很久不能正常的对外提供服务因此,raft论文也给我们提供了一个解决的思路,就是给日志做快照(snapshot)。针对某个日志entry做了快照之后,该entry以及以前的日志都可以被截断。当然,这种方法能解决的我们上面两个问题的本质原因在于:相比日志,快照的存储更为紧凑。日志记录的是事件(比如),而快照通常记录的是数据条目(比如。
2025-04-23 09:12:15
643
原创 go语言实现raft —— PartC
前面的PartA和PartB部分实现了在不宕机的情况下的日志的选举和日志应用。但是如果某个peer异常重启之后是无法正常的加入到集群当中的。为此,需要将Raft的关键信息定时的进行持久化,重启后加载,以保证集群的正常工作。至于哪些条目需要持久化,在论文中都有。主要涉及以下两个函数在本次测试中并不会真正的将这些条目持久化到磁盘中,而是调用了测试框架中的persist.go中的persist类进行持久化。
2025-04-02 23:36:58
837
原创 go语言实现raft —— PartB
在前面PartA的逻辑中,我们实现了一个基本的框架,从领导者选举到领导者发送心跳给各个节点。但是PartA是不包含日志相关的内容的,而PartB主要就是完善PartA的相关内容,将对应的日志消息添加到对应的逻辑中这三个部分的代码是层层递进的关系,需要不断的完善。
2025-03-26 14:07:26
1042
原创 go语言实现raft —— PartA
之所以使用go实现raft是因为raft论文中的伪代码实现给的也是用go语言的逻辑,因此为了避免重复造轮子,提高工作效率,我们这里也采用go语言实现raft。我们知道raft的三个子问题分别是:领导者选举、日志复制和安全性的问题。关于这几个问题的讲述,我在上一篇博客中有讲述到。这里不再赘述,这里主要讲解代码层面上的实现。
2025-03-22 11:07:29
587
原创 raft共识算法
相比于Paoxs,Raft的最大特点就是易于理解。为了这个目标,Raft主要做了两方面的事情问题分解:把共识算法分为三个子问题,分别是领导选举问题、日志复制问题和安全性问题状态简化:对算法做出一些限制,减少状态数量和可能产生的变动。服务器只在三个状态进行切换,服务器之前使用两类RPC进行通信。
2025-03-18 17:23:22
963
原创 原子操作CAS与锁实现
所谓的原子操作就是对原子变量的操作,在多线程的环境下,确保对共享变量的操作在执行时不会被干扰从而避免竞态条件。我们直到加锁可以对一个变量、一段语句或者一个算法进行加锁,而原子操作就是对一个共享变量加锁,对应的共享变量就称为原子变量。原子变量具有原子性,也就是要么全部执行完,要么全部未执行。一个原子操作包括以下3方面上面一段代码就是分别对比使用自旋锁、互斥锁、原子变量以及不加锁时对共享资源的一段操作,下面介绍对于原子变量操作的api函数CAS锁。
2024-12-27 16:36:29
637
原创 MySQL连接池
定义:数据库连接池()是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。大白话:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的 时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度, 还更加安全可靠。这里讲的数据库,不单只是指Mysql,也同样适用于Redis。3 为什么需要使用数据库连接池。
2024-12-25 22:03:06
715
原创 epoll的实现原理
上篇文字我们实现了一个udp的协议栈和tcp的三次握手的。阅读并理解了如何写一个tcp的协议栈,在上一版本的代码中我们发现所使用的用户态的tcp协议栈只能与一个客户端连接通信,因此,本文我们将引入epoll对协议栈进行完善?为什么要自己写一个用户态的协议栈呢?当然在现在我们只是为了熟悉tcp协议栈的内容,但是现实其实确实是需要这样的场景的,将所有东西都委托内核其实会使得内核工作效率降低,因此我们需要自己写一个协议栈提高通信效率,具体的分析可以百度C10K的问题。在实现epoll。
2024-12-13 17:39:50
237
原创 数据传输序列化 Json和protobuf
序列化 (Serialization)将对象的可以,与之相对应的过程称之为反序列化(Unserialization)。。
2024-11-21 18:57:39
1592
原创 Tcp粘包分析
使用过TCP的通信的都可能会遇到这样的问题,代码写的没有问题,但是每次接收到的数据总是怪怪的。有时候接受的长,有时候接收到的数据又比较短。反正数据就是得不到正确的解析,接下来我们分析一下究竟是什么原因导致的?又应该如何解决呢?最后作者还想补充一点关于http协议如何解决TCP粘包问题。
2024-11-15 22:40:57
1427
原创 C++线程池思想
C++线程池是一种并发的技术,它能有效的管理并发线程、减少资源占用和提高程序的性能。本文基于linux的 <pthread> 线程库,使用C++对线程池进行封装,并对底层实现方式进行描述。
2024-11-10 15:31:15
1087
原创 深入浅出理解epoll原理
在 Linux 系统之中有一个核心武器:epoll 池,在高并发的,高吞吐的 IO 系统中常常见到 epoll 的身影。在 Go 里最核心的是 Goroutine ,也就是所谓的协程,协程最妙的一个实现就是异步的代码长的跟同步代码一样。比如在 Go 中,网络 IO 的readwriteGo 配合协程在网络 IO 上实现了。核心就是用 epoll 池来管理网络 fd。实现形式上,后台的程序只需要 1 个就可以负责管理多个 fd 句柄,负责应对所有的业务方的 IO 请求。
2024-10-20 22:09:49
239
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅