自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(76)
  • 收藏
  • 关注

原创 无锁队列—C++内存序最佳实践

在生产者-消费者模型中,两者通过一个共享的任务(消息)队列实现数据传递,同时这个队列需要保证线程安全。读取数据之前,先执行 acquire 屏障;效果:保证数据写入buffer之后,再更新head指针,保证对。首先,为什么不用mutex保护临界区?这样一个队列,可以实现无锁化的线程安全,他是怎么做到的?只讲解常用的两个:release和acquire。2.多生产者-单消费者(SPMC)3.单生产者-多消费者(MPSC)4.单生产者-单消费者(SPSC)中的数据,是生产者在对应。更新前写入的,也就是。

2025-06-03 16:35:44 1275

原创 【golang】channel原理和机制

在select非阻塞模式下,读/写 channel 方法通过一个 bool 型的响应参数,用以标识是否读取/写入成功,实际并不阻塞,而是cas轮询。此时会单纯因为缓冲区满而阻塞该写协程,将其加入到写阻塞队列中,主动park阻塞。读阻塞意味着写入前缓冲区为空,此时写协程会直接从阻塞队列里取出一个协程,直接memmove数据到对方,并唤醒该协程。如果channel无缓冲区,直接唤醒该写协程,读取其元素,也就是强同步的逻辑。也就是目前无法读到数据的情况,将该协程加入读阻塞队列,主动park陷入阻塞。

2025-05-29 16:12:53 2081

原创 浅谈GC机制-三色标记和混合写屏障

可能会出现白色对象3被黑色对象4引用后,原来引用它的灰色对象2同时删除对3的引用,由于不会再次扫描黑色4,故可达对象3会被误判为不可达而被回收。不暂停,并发扫描,从根节点出发,扫描过对象的为黑,下一个可达对象为灰,接下来每一轮从灰节点出发,直到灰节点全部扫描完,只剩下黑和白,回收白色。条件2: 灰⾊对象与它之间的可达关系的⽩⾊对象遭到破坏 (灰⾊同时丢了该⽩⾊)结合了插入写屏障和删除写屏障,为解决并发扫描下的对象丢失问题。条件1: ⼀个⽩⾊对象被⿊⾊对象引⽤ (⽩⾊被挂在⿊⾊下)

2025-05-19 21:45:34 334

原创 GMP深入思考

GMP模型是Go语言中用于管理goroutine调度的核心机制,由G(goroutine)、M(machine,操作系统线程)和P(processor,逻辑处理器)组成。早期的GM模型存在性能问题,如锁竞争和局部性损失,因此引入了P来优化调度。P的数量通常等于CPU核心数,而M的数量是动态变化的。P负责管理本地队列和资源分配,而M负责执行goroutine。当goroutine阻塞时,M会解绑P,P则重新绑定到其他M。调度器通过全局队列、本地队列和网络事件队列来管理goroutine的调度。此外,调度器还支

2025-05-19 18:27:40 403

原创 即时通讯:消息如何保证有序?

各客户端之间的seq可以重复,因为对各个客户端来说seq是用来做本端的消息确认和消息顺序的,对服务端来说,各客户端之间有不同的客户端标识。1.首先考虑的是确保每条消息的序列号唯一性,使用用户id+本地序列号,但这只使用于单聊,在群聊中用户id失效,序列号仍然会重复。目前采用的是这种方式,也就是不根据seq判断顺序,seq只做消息确认,谁先到就先分配msg_id,缺点是偶尔会消息乱序。**问题:使用客户端的seq会造成队头阻塞问题,即seq=1的消息不到达会阻塞后面的消息 **,服务端若要保证消息有序,要。

2024-10-21 09:16:57 7049

原创 即时通讯:群消息的读、写扩散问题

和。这两种模式各有优缺点,适用于不同的场景和需求,尤其在群聊消息的发送和接收环节,它们对系统的性能和可扩展性有重要影响。

2024-10-20 11:05:57 3995

原创 即时通讯 : 未读消息计数

每有一条群聊消息,增加所有人的未读消息计数(如果1个人发1条消息,千人群要操作1000次redis,很快会达到redis写能力瓶颈)2.如果用户打开对话窗口,则客户端向服务端发送未读消息计数清零的请求,窗口打开时,每收到一条消息发送一次清零请求(可优化)群聊的难点在于,一个人发送一条消息,要确保所有人的未读消息计数增加,这带来写扩散的压力。不是的,未读消息计数是客户端上线后拉取的,只要保证客户端能正确获取到未读消息计数就行。客户端在线时,用户若已读消息,客户端要向服务端请求清零消息未读计数,逻辑同单聊。

2024-10-19 21:12:13 3974

原创 即时通讯:单聊消息逻辑

4.msg_server收到回复后,回复ACK给发送方client,发送方会显示消息已发送,但其实此刻没有发送。6.msg_server首先广播该消息到本server的其它client,再转发到route_server。2.msg_server判断消息有效性,每秒发送的消息不能超过限制,无误后转发给db_server。5.msg_server向route_server查询接收方在线状态,不在线则结束,在线则继续。7.route_server广播消息到所有msg_server。

2024-10-19 21:08:25 3357

原创 Dockerfile实战

Dockerfile是一个创建镜像所有命令的文本文件, 包含了一条条指令和说明, 每条指令构建一层, 通过 docker build命令,根据Dockerfile的内容构建镜像,因此每一条指令的内容, 就是描述该层如何构建.有了 Dockefile, 就可以制定自己的docker镜像规则,只需要在Dockerfile上添加或者修改指令, 就可生成 docker 镜像.

2024-10-14 19:51:34 3696

原创 etcd入门到实战

etcd是一个分布式键值存储数据库键值存储存储协议是 key—value 的形式,类似于redis分布式:具有分布式特性、每个etcd实例作为集群中的一个节点,通过分布式锁, leader选举保障可靠的分布式协同数据库持久化存储、与redis的主内存存储不同,etcd主持久化到磁盘,同MySQL。

2024-10-14 17:29:12 5834

原创 TCP四次挥手过程详解

深入解析tcp四次挥手

2024-10-02 23:26:09 6942 1

原创 Linux内存管理方式

Linux 内存管理系统通过虚拟内存、物理内存管理、内存保护、页面置换、内存分配器等机制,实现高效的内存使用和保护。在多核和多任务环境中,操作系统不断优化这些机制,以提高系统的性能和稳定性。推荐学习 https://xxetb.xetslk.com/s/p5Ibb。

2024-09-15 19:06:02 3301

原创 CAS与原子操作

原子操作是一种在执行过程中不会被中断的操作。它要么完全执行成功,要么完全不执行,确保在操作完成之前其他线程不会看到操作的中间状态。

2024-09-06 22:04:25 829

原创 fork的原理

后,子进程进入就绪队列,等待调度程序的调度。当调度程序决定切换到子进程时,子进程会从复制的父进程上下文开始执行。中一个关键的优化点。父子进程共享同一块物理内存,只是在内存页被写入时才进行实际的物理内存复制。推荐学习 https://xxetb.xetslk.com/s/p5Ibb。完成的,该函数负责创建子进程并复制父进程的各种信息。的效率,特别是对于不需要立即修改内存的场景,例如。的返回点开始执行,只不过它返回的是。从 Linux 内核源码角度来看,在内存管理中,COW 技术是。,加载新的程序映像。

2024-09-05 10:17:14 660

原创 堆和栈的区别

栈(Stack)栈是静态分配的内存区域,大小在程序运行时由编译器确定。在 Linux 内核中,栈的内存是通过固定大小的连续内存块分配的,并且遵循“后进先出”的规则。这意味着栈中的内存是按顺序压入和弹出的,通常用于局部变量、函数调用信息(如返回地址、参数、局部变量等)。堆(Heap)堆是动态分配的内存区域,大小可以在程序运行时通过系统调用(如malloc或kmalloc)动态请求。在 Linux 内核中,堆是通过内存管理子系统动态分配的,主要用于需要动态内存分配的场景。

2024-09-05 10:16:34 732

原创 协程源码剖析(三) 调度器设计实现

先来看协程调度器的结构体中处理调度的部分。

2024-09-04 13:54:36 3494

原创 进程和线程的区别

由于同一进程内的线程共享虚拟内存地址空间,没有切换页表(即切换cr3寄存器),也不会刷新TLB,内核只需保存当前线程的寄存器状态、程序计数器、堆栈指针等,开销相对较小。寄存器指向新的页表),TLB失效,切换到新进程后查页表速度很慢,因为缓存命中率低。虚拟内存与物理内存的映射需要查页表,TLB缓存记录映射关系,可以加快查询速度,而上下文切换时会切换页表(在Linux中,进程和线程是统一调度的,调度器只负责调度。在内核的视角,进程与线程都被视为。,每一个进程或线程对应一个。实例,不论进程或线程。

2024-09-04 09:22:30 3946

原创 vector底层原理(二)

根本原因:引用是别名,不是对象,没有实际地址,不能创建引用的指针,不能创建引用的引用,因此不能通过操作符[]获取引用的引用。推荐学习 https://xxetb.xetslk.com/s/p5Ibb。的存储机制要求每个元素都能独立存在和管理,这与引用的特性不符。直接原因:引用没有独立的存储空间,因此无法作为。二、vector的元素为什么不能是引用?

2024-09-03 21:57:06 344

原创 vector底层原理

2024-09-02 21:18:51 566 1

原创 Docker入门——什么是Docker

不推荐将容器于虚拟机类比,虚拟机虚拟了cpu等硬件资源,而容器只是做进程的管理,容器的进程隔离使用的仍然是操作系统提供的隔离机制如namespace。应用程序的源码全部复制,而依赖环境如特定版本的操作系统、编译器等环境由文字描述记录,在保证轻量的同时确保依赖环境的一致性。docker是一种容器化技术,具体来说它是将应用程序及其依赖环境打包的一种软件,用于保证开发环境的一致性。docker提供将应用程序及其依赖环境打包成镜像,使用容器提供的隔离环境运行应用程序。没错,它们使用的是宿主机的cpu、内存等资源。

2024-09-02 20:32:47 3595

原创 FastDFS架构分析

FastDFS主要的功能包括:文件存储,同步和访问,。FastDFS非常适用于基于文件服务的站点,。FastDFS由、**存储服务器(storage server)客户端(client)**三个部分组成,主要解决海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size < 500MB)为载体的在线服务,例如图片分享和视频分享网站。FastDFS架构如下所示:每个storage在启动后会所属group、最近同步完成时间,并。

2024-08-29 16:01:17 3581

原创 FastDFS集群同步机制

答案:同步线程进行storage同步时,会先读取对方的.mark同步文件,其中包含该storage的同步记录,其中binlog_offset字段记录了上一次同步binlog的位置。答:源storage写入文件后记录该操作到binlog文件,用操作符的大小写区分该操作是源文件操作还是副本文件操作,源storage的监听线程(多个)捕捉到新记录,4.已有A、B、C三个storage,我现在上传一个文件到A,然后发起请求下载,会不会出现从B请求下载,但此时B没有同步文件,导致下载失败的情况?

2024-08-29 15:58:40 4567

原创 TCP三次握手过程详解

三次握手过程:客户端视角:1.客户端调用connect,开启计时器,发送SYN包,如果重传超时,认为连接失败2.如果收到服务端的ACK,则进入ESTABLISHED状态3.清除重传计时器,发送ACK,开启保活计时器:如果再次收到ACK+SYN说明服务端没收到第三次握手包,进行了重传,此时客户端会重传ACK服务端视角:1.listen()创建半连接队列和全连接队列2.收到SYN包,如果半连接队列已满,丢弃该连接,否则为该连接创建一个socket加入到半连接队列中。

2024-08-27 22:40:27 5898

原创 进程间通信方式详解

由于每个进程的用户空间都是独立的,不能相互访问,这时就需要借助内核空间来实现进程间通信,原因很简单,每个进程都是共享一个内核空间。Linux 内核提供了不少进程间通信的方式,其中最简单的方式就是管道,管道分为「匿名管道」和「命名管道」。匿名管道顾名思义,它没有名字标识,匿名管道是特殊文件只存在于内存,没有存在于文件系统中,shell 命令中的「」竖线就是匿名管道,通信的数据是无格式的流并且大小受限,通信的方式是单向的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道,再来。

2024-08-20 20:38:43 5634

原创 http1.0,1.1,2.0的区别

http1.0、http1.1、http2.0的优缺点

2024-08-10 11:06:08 1128

原创 grpc使用教程

protobuf、rpc使用详解

2024-08-10 09:49:21 5152

原创 TCP为什么需要四次挥手?

为什么是四次挥手?能不能三次?

2024-07-29 21:09:51 9055 3

原创 C语言实现多线程下载

高性能多线程下载方案——curl

2024-07-29 08:55:17 894

原创 MySQL架构和工作流程

详解MySQL体系结构

2024-07-06 16:26:54 452

原创 MySQL日志——redolog

在mysql提交一个事务后,这个事务所作的数据修改并不会直接保存到磁盘文件中,而是先保存在buffer pool缓冲区中,在需要读取数据时,先从缓冲区中找,没找到再去磁盘找,加之每次提交事务都将数据写入磁盘的效率低下,所以引入了buffer pool缓冲区。因此,redo log记录了一个事务对数据页的修改,这个记录与undolog不同,是物理层面的,比如。提交一个事务后,先将redo log持久化磁盘,就可以保证这个事务修改的数据被持久化了。为什么需要redo log?

2024-06-18 20:01:56 3195

原创 MySQL日志——undolog

比如当 delete 一条记录时,undo log 中会把记录中的内容都记下来,然后执行回滚操作的时候,就读取 undo log 里的数据,然后进行 insert 操作。,也就是在事务提交之前,可以恢复到事务开始前的数据库状态,相当于已经执行的事务操作没有发生过一样,这是怎么做到的?了解redis的朋友都知道redis的日志是为了实现数据的持久化,而mysql将数据存储在磁盘文件,没有持久化的问题,为什么还需要日志呢?,但数据库的状态为当前状态,需要记录事务开始前的数据库状态,以便进行回滚恢复。

2024-06-18 17:42:02 3417

原创 redis大key对持久化的影响

字节二面原题

2024-06-18 09:29:21 1193

原创 redis持久化方式—RDB

redis持久化方案——RDB

2024-06-18 03:45:00 3519

原创 深入理解redis持久化—AOF日志

redis持久化策略

2024-06-18 02:00:00 4938

原创 redis数据结构—哈希表

redis的底层数据结构——hash table

2024-06-17 19:52:30 3736

原创 Copy On Write写时复制原理

操作系统——fork写时复制机制详解

2024-06-17 12:18:51 3731

原创 redis存储结构

redis的存储原理

2024-06-17 11:42:53 3906

原创 数据库MySQL——从0到1入门教程

MySQL小白入门教程

2024-06-14 16:36:38 3111

原创 glibc函数malloc的工作原理

1.小于128kB的空间,使用内存池(在堆上)或brk或sbrk系统调用在堆上分配2.大于128kB的空间,使用mmap在文件映射区分配| 栈 (Stack) || || 映射区域 || (mmap) || || 堆 (Heap) || BSS段 || 数据段 || 代码段 |小于128 KB的内存分配对于小于128 KB的内存分配请求,glibc的内存分配器通常会使用brk系统调用来增加程序的堆(heap)空间。堆是从进程的虚拟内存空间中分配的连续内存区域。通过brk或sbrk。

2024-06-11 00:15:00 3346

原创 C语言字符串的设计缺陷

Redis解决c语言字符串缺陷——SDS

2024-06-04 02:30:00 2910

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除