当前位置: 首页 > news >正文

PostgreSQL数据库内核(三):缓冲区管理器

文章目录

    • 共享缓冲区基础知识
      • 逻辑读和物理读
      • LRU算法和CLOCK时钟算法
    • 共享缓冲区管理器结构
      • 共享缓冲表层
      • 共享缓冲区描述符层
      • 共享缓冲页层
    • 共享缓冲区管理器工作流程
      • 初始化缓冲区
      • 读缓冲区
      • 淘汰策略
      • 共享缓冲区锁

共享缓冲区基础知识

通常数据库系统都会在内存中预留buffer缓冲空间用于提升读写效率,因为与内存读写交互效率远大于与磁盘的读写效率,而缓冲区管理器管理着缓冲区内存空间,将热数据加载到内存中以减少直接的磁盘读写,并维持这部分数据在缓冲池中的状态/锁管理,充当着读写进程和操作系统之间的协同者角色;
共享缓冲区管理器在设计上需要考虑的核心问题是:缓冲区大小设计+提升缓冲区命中率+制定合理缓冲区回收策略+保证多并发下的一致性问题。
在开始需要先了解一些基础知识。

逻辑读和物理读

逻辑读和物理读的区别在pg后台进程获取数据的过程中是否涉及到磁盘读,逻辑读过程中pg后台进程直接读从共享缓冲区获取到的数据页,物理读需要从借助操作系统从磁盘读取数据并加载到内存中再返回给读写程序。
做个实验先创建表并插入数据,通过expain analyze分析看一下物理读和逻辑读的差异。

postgres=# create table yzg(a int ,b varchar);
postgres=# insert into yzg (1,'a');
postgres=# insert into yzg select * from yzg;
INSERT 0 1
...
postgres=# insert into yzg select * from yzg;
INSERT 0 524288

构造查询语句SELECT * FROM yzg,发现命中了缓冲池中的4640个页(这里的yzg整个表大小也是4640个页,因为新建的pg环境没有其他并行连接和查询),这里就是逻辑读的过程;

postgres=# EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM yzg;QUERY PLAN
---------------------------------------------------------------------------------------------------------------Seq Scan on yzg  (cost=0.00..15125.76 rows=1048576 width=6) (actual time=0.015..140.675 rows=1048576 loops=1)Buffers: shared hit=4640Planning Time: 0.051 msExecution Time: 222.198 ms
(4 rows)postgres=# SELECT
postgres-#     nspname AS schema_name,
postgres-#     relname AS table_name,
postgres-#     pg_total_relation_size(C.oid) AS total_size, -- 包括表、索引、toast表等的总大小
postgres-#     pg_relation_size(C.oid) AS heap_size,       -- 表的堆大小
postgres-#     (pg_relation_size(C.oid) / (1024 * 8))::bigint AS pages -- 表占用的页面数(假设页面大小为8KB)
postgres-# FROM g_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) WHERE nspname || '.' || relname = 'public.yzg';schema_name | table_name | total_size | heap_size | pages
-------------+------------+------------+-----------+-------public      | yzg        |   38060032 |  38010880 |  4640
(1 row)

如果我们把数据库down掉后再启动数据库,缓冲区数据就会被清理,再看执行计划产生了物理读;


postgres=# EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM yzg;QUERY PLAN
---------------------------------------------------------------------------------------------------------------Seq Scan on yzg  (cost=0.00..15125.76 rows=1048576 width=6) (actual time=0.032..161.956 rows=1048576 loops=1)Buffers: shared read=4640Planning:Buffers: shared hit=15 read=8Planning Time: 2.666 msExecution Time: 243.906 ms
(6 rows)

LRU算法和CLOCK时钟算法

将磁盘数据页block加载到内存以提升查询效率的必要性已经不言而喻了,但是通常内存肯定没有磁盘空间充足,其能够缓存的数据空间有限,需要一定策略来决定当内存满时应该替换掉哪些页面,也就是缓存置换算法。
LRU(Least Recently Used)算法是一种常用的决定当内存满时应该替换掉哪个页面的置换算法,其核心思想是优先淘汰最近最少使用的页面,假设如果一个页面最近被访问过那么它很可能很快会被再次访问,反之如果一个页面很久没被访问那么它很可能在未来也不会被访问。
CLOCK时钟算法是另一种在数据库缓冲池中使用的更节省资源的LRU替代方案,它试图在访问历史和内存中维持一个平衡,其再内存页面上维护一个“引用位”(reference bit)来判断页面是否最近被访问过,不需要维护完整的访问历史链表,而是通过简单的位标志来判断页面的使用情况,在实现上更加简单消耗的资源也更少但可能不如 LRU 算法精确。
两者都是缓存置换算法,但CLOCK算法在实现上更简单,并且可以减少内存访问次数,但LRU算法在实现上更复杂,pg使用时钟算法,oracle使用LRU算法。

共享缓冲区管理器结构

共享内存缓冲区可以被数据库多个子进程共享访问,缓冲区管理器维护着这块缓冲区的数据一致性并返回真实的数据页page,按照《PostgreSQL指南》将缓冲区管理器分三层:缓冲表、缓冲区描述符、缓冲页,但这里的层次划分是为了便于理解而进行的逻辑划分,如下图。
在这里插入图片描述

在代码上共享内存缓冲区的目录地址是src/backend/storage/buffer/,总代码量6000行+,其中:
1.buf_init.c 是缓冲区管理器的初始化入口,在启动数据库进程时候会初始化并分配1个共享内存缓冲区,并初始化缓冲表、缓冲区描述符和缓冲页。
2.buf_table.c 是缓冲表管理器,维护着缓冲区管理器中缓冲区的索引,缓冲区管理器通过缓冲表获取缓冲区描述符的索引项。
3.bufmgr.c 是缓冲区管理器核心代码,处理缓冲区管理器中缓冲区的访问并返回真实的数据页page。
4.freelist.c 是缓冲区管理器中缓冲区的淘汰策略,缓冲区不够用时调用淘汰策略来淘汰缓冲区。
5.localbuf.c 是本地缓冲区管理器,用于管理本地缓冲区,本地缓冲区是进程私有的缓冲区,用于缓存进程自己访问的数据.。
在这里插入图片描述

共享缓冲表层

共享缓冲表层代码实现在buf_table.c文件中,其函数都是针对hash表(dynahash.c)的查/增/删操作,这个hash表是全局共享的在InitBufferPool()中创建。
在这里插入图片描述

其中BufTableHashCode函数将在hash表中找到入参buffer_tags对应的buffer_id:

uint32 BufTableHashCode(BufferTag *tagPtr)
{return get_hash_value(SharedBufHash, (void *) tagPtr);
}

buffer_tag数据库子进程对于共享缓冲区的输入,能够唯一标识请求的page页,其中RelFileNode的属性分别是表对象oid/数据块oid/表空间oid,页面的forknumber(分别为0、1、2)(0=表和索引块,1=fsm,2=vm)页面number(页面属于哪个块)。例如{(16888, 16389, 39920), 0, 8}标签表示在某个表空间(oid=16888)某个数据库(oid=16389)的某表(oid=39920)的0号分支( 0代表关系表本体)的第8号页面。

// 映射关系
typedef struct
{BufferTag	key;			/* Tag of a disk page */int			id;				/* Associated buffer ID */
} BufferLookupEnt;  
// BufferTag结构定义在buf_internals.h中,可以唯一标识数据页
typedef struct buftag
{RelFileNode rnode;			/* physical relation identifier */ForkNumber	forkNum;BlockNumber blockNum;		/* blknum relative to begin of reln */
} BufferTag;
// 关系定义包含表空间id+dbid+表id
typedef struct RelFileNode
{Oid			spcNode;		/* tablespace */Oid			dbNode;			/* database */Oid			relNode;		/* relation */
} RelFileNode;

共享缓冲区描述符层

共享缓冲区描述符层也维护了1个BufferDesc元素构成的BufferDescriptors数组,该数组是所有数据库进程共享的,数组创建后由BufferStrategyControl负责管理,每个BufferDesc包含BufferTag和buf_id信息以及freeNext。
在这里插入图片描述

其中有个概念是freelist数组用于缓存空闲的BufferDesc,是BufferDescriptors数组中某些描述符的引用,当缓冲池管理器需要一个空闲的缓冲区时会首先检查freelist并从中取出空闲缓冲区的引用,这个描述符将从freelist中移除并被标记为已分配状态,当一个缓冲区不再需要时它的描述符会被放回freelist中。

共享缓冲页层

共享缓冲页层即buffers[]数组,存储真实的数据页page,并与共享描述符一一对应。

共享缓冲区管理器工作流程

初始化缓冲区

shared_buffers参数是基于系统内存大小动态计算的,对于<8GB内存的系统默认值为 128MB,对于>8GB,<16GB内存的系统默认值为系统内存的 1/4,对于>16GB内存的系统默认值为 4GB。

postgres=# show shared_buffers ;shared_buffers
----------------128MB

初始化流程如下:

main(int argc, char *argv[])
--> PostmasterMain(argc, argv);--> reset_shared();     // Set up shared memory and semaphores.--> CreateSharedMemoryAndSemaphores(); // Creates and initializes shared memory and semaphores.--> CalculateShmemSize(&numSemas); // Calculates the amount of shared memory and number of semaphores needed.--> add_size(size, BufferShmemSize());--> PGSharedMemoryCreate(size, &shim);--> InitShmemAccess(seghdr);--> InitBufferPool();  // 初始化缓冲池// 1. 初始化buffer descriptor--> ShmemInitStruct("Buffer Descriptors",NBuffers * sizeof(BufferDescPadded),&foundDescs);  // 2. 初始化buffer pool--> ShmemInitStruct("Buffer Blocks", NBuffers * (Size) BLCKSZ, &foundBufs);--> StrategyInitialize(!foundDescs);   // 3. 初始化 buffer table--> InitBufTable(NBuffers + NUM_BUFFER_PARTITIONS);--> ShmemInitHash("Shared Buffer Lookup Table", size, size, &info, HASH_ELEM | HASH_BLOBS | HASH_PARTITION);--> hash_create(name, init_size, infoP, hash_flags);

读缓冲区

读取缓冲区的流程比较简单,缓冲表根据输入(buftag)输出缓冲区描述符buf_id并找到缓冲区描述符,若buf_id值大于0表示命中,命中后pin住该页使之不能被淘汰掉,修改BufferDesc->state值,refcount+1,usage+1,没有命中根据淘汰策略淘汰页再从磁盘读取页到缓冲区槽位,然后根据缓存区槽位返回对应的buf_id。
数据库子进程调用ReadBufferExtended ->ReadBuffer_common函数读取buffer,其中ReadBuffer_common会调用核心函数BufferAlloc来真正意义上进行缓冲区扫描与加载,其流程图如下:
在这里插入图片描述

函数梳理:

Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
--> ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);--> ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,forkNum, blockNum, mode, strategy, &hit);--> BufferAlloc(smgr, relpersistence, forkNum, blockNum, strategy, &found);--> INIT_BUFFERTAG(newTag, smgr->smgr_rnode.node, forkNum, blockNum); /* create a tag so we can lookup the buffer */--> BufTableHashCode(&newTag); // 哈希函数输入buftag,输出哈希值--> get_hash_value(SharedBufHash, (void *) tagPtr);--> buf_id = BufTableLookup(&newTag, newHash);  // 根据buftag,查找缓冲表,获得bug_id,如果命中的话,如果找不到,返回-1--> hash_search_with_hash_value(SharedBufHash,(void *) tagPtr,hashcode,HASH_FIND,NULL);// 如果命中,返回,如果没有命中,继续执行--> StrategyGetBuffer(strategy, &buf_state);	// 获取一个空闲可用的buffer,返回bufferdesc, 默认策略是NULL--> GetBufferFromRing(strategy, buf_state);--> BufTableInsert(&newTag, newHash, buf->buf_id); // 将新获取的buf_id,插入到缓冲表中--> smgrread(smgr, forkNum, blockNum, (char *) bufBlock); // 从磁盘读到buffer

pinbuffer函数用于“pin”一个缓冲区,当缓冲区被pin时意味着它正被一个或多个事务或查询使用,因此不能被缓冲池管理器淘汰或替换:
在这里插入图片描述

startBufferIo函数用于启动一个缓冲区I/O操作,当缓冲区中的数据需要从磁盘读取或写入磁盘时StartBufferIO()会被用来发起从磁盘读取数据的 I/O 请求,同样当缓冲区中的数据被修改并且需要持久化到磁盘时也会调用此函数来执行写操作:
在这里插入图片描述

淘汰策略

strategygetbuffer函数是缓冲区管理策略的一部分用于获取一个缓冲区,决定从缓冲池中获取哪个缓冲区,如果缓冲区不存在或已被淘汰那么它会根据当前的策略选择一个空闲或可替换的缓冲区,并可能触发 I/O 操作以加载或写入数据。
在这里插入图片描述

共享缓冲区锁

待续。

相关文章:

PostgreSQL数据库内核(三):缓冲区管理器

文章目录 共享缓冲区基础知识逻辑读和物理读LRU算法和CLOCK时钟算法 共享缓冲区管理器结构共享缓冲表层共享缓冲区描述符层共享缓冲页层 共享缓冲区管理器工作流程初始化缓冲区读缓冲区淘汰策略共享缓冲区锁 共享缓冲区基础知识 通常数据库系统都会在内存中预留buffer缓冲空间…...

[log4cplus]: 快速搭建分布式日志系统

关键词: 日志系统 、日志分类、自动分文件夹、按时间(月/周/日/小时/分)轮替 一、引言 这里我默认看此文的我的朋友们都已经具备一定的基础,所以,我们本篇不打算讲关于log4cplus的基础内容,文中如果涉及到没有吃透的点,需要朋友们动动自己聪明的脑袋和发财的手指,进一…...

redis I/O复用机制

I/O复用模型 传统阻塞I/O模型 串行化处理&#xff0c;就是要等&#xff0c;假如进行到accept操作&#xff0c;cpu需要等待客户端发送的数据到tcp接收缓冲区才能进行read操作&#xff0c;而在此期间cpu不能执行任何操作。 I/O复用 用一个进程监听大量连接&#xff0c;当某个连…...

Adobe PhotoShop - 制图操作

1. 排布照片 菜单 - 视图 - 对齐&#xff1a;打开后图层将会根据鼠标的移动智能对齐 菜单 - 视图 - 标尺&#xff1a;打开后在页面出现横纵标尺&#xff0c;方便图层的对齐与排列 2. 自动生成全景照 在日常处理中&#xff0c;我们常常想要将几张图片进行拼接获得一张全景图&…...

Mysql 中的Undo日志

在 MySQL 的 InnoDB 存储引擎中&#xff0c;Undo Log 是用于实现数据库事务的回滚功能的一种日志。Undo Log 记录了对数据的修改&#xff0c;以便在事务出现问题时可以恢复到之前的状态。下面将介绍 Undo Log 的结构和样本数据。 Undo Log 的基本概念 目的: Undo Log 的主要目…...

虹软科技25届校招笔试算法 A卷

目录 1. 第一题2. 第二题3. 论述题 ⏰ 时间&#xff1a;2024/08/18 &#x1f504; 输入输出&#xff1a;ACM格式 ⏳ 时长&#xff1a;2h 本试卷分为不定项选择&#xff0c;编程题&#xff0c;必做论述题和选做论述题&#xff0c;这里只展示编程题和必做论述题&#xff0c;一共三…...

C++ | Leetcode C++题解之第345题反转字符串中的元音字母

题目&#xff1a; 题解&#xff1a; class Solution { public:string reverseVowels(string s) {auto isVowel [vowels "aeiouAEIOU"s](char ch) {return vowels.find(ch) ! string::npos;};int n s.size();int i 0, j n - 1;while (i < j) {while (i < …...

Kubernetes拉取阿里云的私人镜像

前提条件 登录到阿里云控制台 拥有阿里云的ACR服务 创建一个命名空间 获取仓库的访问凭证&#xff08;可以设置固定密码&#xff09; 例如 sudo docker login --usernameyourAliyunAccount registry.cn-guangzhou.aliyuncs.com 在K8s集群中创建一个secret 使用kubectl命令行…...

Leetcode每日刷题之118.杨辉三角

1.题目解析 杨辉三角作为一个经典的数学模型&#xff0c;其基本原理相信大家已经耳熟能详&#xff0c;这里主要是在学习了vector之后&#xff0c;对于本题有了新的解法&#xff0c;更加简便。关于vector的基本使用详见 面向对象程序设计(C)之 vector&#xff08;初阶&#xff0…...

【ARM 芯片 安全与攻击 5.2 -- 芯片中侧信道攻击与防御方法介绍】

文章目录 什么是 Speculation Barriers?如何使用 Speculation Barriers?什么是 PAN?如何启用 PAN?使用 PAN 保护操作系统Spectre 攻击防御示例Meltdown 攻击防御示例Summary什么是 Speculation Barriers? Speculation Barriers,是一种防止处理器在投机执行中泄漏敏感信息…...

XSS-games

XSS 1.XSS 漏洞简介2.XSS的原理3.XSS的攻击方式4.XSS-GAMESMa SpaghetJefffUgandan KnucklesRicardo MilosAh Thats HawtLigmaMafiaOk, BoomerWW3svg 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Sc…...

日撸Java三百行(day25:栈实现二叉树深度遍历之中序遍历)

目录 一、栈实现二叉树遍历的可行性 二、由递归推出栈如何实现中序遍历 1.左子树入栈 2.根结点出栈 3.右子树入栈 4.实例说明 三、代码实现 总结 一、栈实现二叉树遍历的可行性 在日撸Java三百行&#xff08;day16&#xff1a;递归&#xff09;中&#xff0c;我们讲过…...

【vue讲解:ref属性、动态组件、插槽、vue-cli创建项目、vue项目目录介绍、vue项目开发规范、es6导入导出语法】

0 ref属性&#xff08;组件间通信&#xff09; # 1 ref属性放在普通标签上<input type"text" v-model"name" ref"myinput">通过 this.$refs[myinput] 拿到的是 原生dom对象操作dom对象&#xff1a;改值&#xff0c;换属性。。。# 2 ref属…...

ubuntu:最新安装使用docker

前言 系统&#xff1a;ubuntu 22.04 desktop 目的&#xff1a;安装使用docker 安装小猫猫 没有安装包的&#xff0c;可以自己去瞅瞅&#xff0c;这里不提供下载方式 sudo dpkg -i ./cat-verge_1.7.5_amd64.deb 在应用里&#xff0c;打开这个软件&#xff0c;并开启系统猫猫 配…...

Linux ssh 免密失效

sudo chmod -R 777 /home/xxx sudo chown -R xxx:xxx /home/xxx 为什么我输入这两条指令后&#xff0c;ssh免密失效了&#xff1f; 当你使用 sudo chmod -R 777 /home/xxx 和 sudo chown -R xxx:xxx /home/xxx 这两条指令后&#xff0c;可能会导致 SSH 免密登录失效的原因有以…...

k8s上部署ingress-controller

一、安装helm仓库 # helm pull ingress-nginx/ingress-nginx 二、修改 三、运行 # kubectl label nodes node01.110111.cn ingresstrue# kubectl label nodes node02.110112.cn ingresstrue# helm upgrade --install ingress-nginx -n ingress-nginx . -f values.yaml 四、检…...

Android 13 about launcher3 (1)

Android 13 Launcher3 android13#launcher3#分屏相关 Launcher3修改 wm density界面布局不改变 /packages/apps/Launcher3/src/com/android/launcher3/InvariantDeviceProfile.java Launcher的默认配置加载类&#xff0c;通过InvariantDeviceProfile方法可以看出&#xff0c;…...

服务器数据恢复—raid5阵列热备盘未全部启用导致阵列崩溃的数据恢复案例

服务器存储数据恢复环境&#xff1a; 一台EMC某型号存储中有一组RAID5磁盘阵列。该raid5阵列中有12块硬盘&#xff0c;其中2块硬盘为热备盘。 服务器存储故障&#xff1a; 该存储raid5阵列中有两块硬盘离线&#xff0c;只有1块热备盘启用替换掉其中一块离线盘&#xff0c;另外…...

HTML—css

css概述 C S S 是 C a s c a d i n g S t y l e S h e e t s &#xff08; 级 联 样 式 表 &#xff09; 。 C S S 是 一 种 样 式 表 语 言 &#xff0c; 用 于 为 H T M L 文 档 控 制 外 观 &#xff0c; 定 义 布 局 。 例 如 &#xff0c; C S S 涉 及 字 体 、 颜 色 、…...

IO多路复用(Input/Output Multiplexing)

IO多路复用(Input/Output Multiplexing) 是一种在单个线程中管理多个输入/输出通道的技术。它允许一个线程同时监听多个输入流(如网络套接字、文件描述符等),并在有数据可读或可写时进行相应的处理,而不需要为每个通道创建一个独立的线程。这种技术主要用于处理并发连接…...

android与pc 用socket无线通信

今天做一个android与pc通信的小demo&#xff08;不是wifi&#xff0c;蓝牙&#xff09;android为客户端&#xff0c;pc为服务器&#xff08;一对多&#xff09;。pc代码很简单&#xff0c;android客户端代码也不难&#xff0c;但是有一点不太明白就是在客户端向服务器发送消息时…...

【流程引擎】springboot完美集成activiti工作流方案

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;一套完整并且实际运用在多套项目中的案例&#xff0c;满足日常业务流程审批需求。 项目源码配套文档获取&#xff1a;本文末个人名片直接获取。 一、项目形式 springboot…...

11、常见API

01、String类概述及构造方法简介 一、字符串 由多个字符组成的一串数据 二、简介 String类代表的是一个字符串。字符串对象在开发中是最常见的。为了方便我们对字符串进行操作&#xff0c;java就把字符串用对象进行了封装&#xff0c;这个封装就是String类 三、String类的构造方…...

渗透第三次作业

目录 第一关Ma Spaghet! 第二关Jefff&#xff1a; 第三关&#xff1a;Ugandan Knuckles 第四关&#xff1a;Ricardo Milos 第五关&#xff1a; Ah Thats Hawt 第一关Ma Spaghet! <h2 id"spaghet"></h2> <script>spaghet.innerHTML (new URL(…...

Python自动化:解锁高效工作与生产力的密钥

在当今快节奏的数字时代&#xff0c;自动化已成为提升工作效率、优化流程、减少人为错误的不可或缺的工具。Python&#xff0c;作为一种功能强大、易于学习且应用广泛的编程语言&#xff0c;在自动化领域扮演着举足轻重的角色。无论是数据处理、Web自动化、软件测试&#xff0c…...

Sentinel1.8.1 控制台改造

Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的入口&#xff0c;它为用户提供了机器自发现、簇点链路自发现、监控、规则配置等功能。在 Sentinel 控制台上&#xff0c;我们可以配置规则并实时查看流量控制效果。 本项目是在Sentinel控制台1.8.1的基础上改造的&…...

设计模式(2)行为型模式和七大原则

1、目标 本文的主要目标是学习设计模式的行为型模式并举例说明 2、行为型模式 2.1 观察者模式&#xff08;Observer&#xff09; 观察者模式是对象之间存在一对多的依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有依赖它的对象都会得到通知并自动更新&…...

学懂C++(三十一):高级教程——深入详解C++高级多线程编程技术之锁优化与替代

引言 随着多核处理器的普及&#xff0c;多线程编程技术已经成为提高应用程序性能的关键手段。在多线程环境下&#xff0c;如何高效、安全地管理线程之间的共享资源是开发者面临的主要挑战。传统的锁机制&#xff0c;如互斥锁&#xff08;Mutex&#xff09;、临界区&#xff08;…...

Linux - 基础工具使用

文章目录 一、yum1、介绍2、功能3、语法4、使用 二、rzsz1、安装rzsz的指令2、介绍3、使用 三、vim基础使用1、介绍2、基础使用 四、gcc/g使用1、生成可执行文件过程2、语法3、常用选项4、编译过程5、动静态库6、包含头文件的多文件编译7、链接外部库 一、yum 1、介绍 Linux中…...

理解线程id和简单封装原生线程库

一、理解线程id 首先我们要知道给用户提供的线程id不是内核里面LWP&#xff08;轻量级进程id&#xff09;&#xff0c;而是pthread库自己维护的一个唯一值。 我们理解为什么线程id不是内核里面LWP&#xff0c;因为用户没有权限使用内核里面的字段&#xff0c;那是专门给OS管理…...

Unified 阻抗控制 architecture、framework、approach

Unified 阻抗控制&#xff08;Unified Impedance Control&#xff09;作为一种控制策略&#xff0c;其architecture&#xff08;架构&#xff09;、framework&#xff08;框架&#xff09;和approach&#xff08;方法&#xff09;为&#xff1a; 一、Unified 阻抗控制 Archite…...

Java后端面试题(mq相关)(day9)

目录 为什么用MQ&#xff1f; 异步 、削峰、解耦1. 异步处理2. 解耦3. 削峰填谷 Exchange类型什么是死信队列&#xff1f;如何保证消息的可靠性&#xff1f;RabbitMQ中如何解决消息堆积问题?RabbitMQ中如何保证消息有序性?如何防止消息重复消费&#xff1f;(如何保证消息幂等…...

算法-华为OD机试-识别有效的IP地址和掩码并进行分类统计

1.描述 见牛客网 https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a74356822. 分析 根据题目要求&#xff0c;分为以下几步 1. 提取IP地址和子网掩码 我们首先需要拆分输入的每一行&#xff0c;分别提取IP地址和子网掩码&#xff0c;并检查它们的合法性。 2.…...

钉钉开发网页应用JSAPI前端授权鉴权nodejs实现

钉钉开发网页应用JSAPI前端授权鉴权nodejs实现 使用钉钉进行H5网页开发的时候&#xff0c;需要调用一些钉钉提供具有原生能力的api&#xff0c;要调用这些api需要进行jsapi授权。 详见官方文档&#xff08;可选&#xff09;开发网页应用前端 - 钉钉开放平台 (dingtalk.com) 官方…...

uniapp 自定义全局弹窗

自定义全局弹窗可在js和.vue文件中调用&#xff0c;unipop样式不满足&#xff0c;需自定义样式。 效果图 目录结构 index.vue <template><view class"uni-popup" v-if"isShow"><view class"uni-popup__mask uni-center ani uni-cust…...

element+-ui图片无法使用--安装

element-ui图片无法使用 安装npm install element-plus/icons-vue 注册 // main.jsimport * as ElementPlusIconsVue from element-plus/icons-vueconst app createApp(App) for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, compo…...

Python编码系列—Python ORM(对象关系映射):高效数据库编程实践

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…...

一次日志记录中使用fastjson涉及到ByteBuffer的教训

背景 目前本人在公司负责的模块中&#xff0c;有一个模块是负责数据同步的&#xff0c;主要是将我们数据产线使用的 AWS Dynamodb 同步的我们的测试QA 的环境的 MongoDB 的库中&#xff0c;去年开始也提供了使用 EMR 批量同步的功能&#xff0c;但是有时候业务也需要少量的数据…...

掌握TCP连接管理与流量控制:从零开始

文章目录 1. TCP连接管理1.1 三次握手&#xff08;Three-way Handshake&#xff09;1.2 四次挥手&#xff08;Four-way Handshake&#xff09;1.3 TCP连接管理的重要性 2. TCP流量控制2.1 滑动窗口&#xff08;Sliding Window&#xff09;2.2 拥塞控制&#xff08;Congestion C…...

python提取b站视频的音频(提供源码

如果我想开一家咖啡厅&#xff0c;那么咖啡厅的音乐可得精挑细选&#xff01;又假设我非常喜欢o叔&#xff0c;而o叔只在b站弹钢琴&#xff0c;那这时候我就得想方设法把b站的视频转为音频咯&#xff01; 一、首先打开网页版bilibili&#xff0c;按F12&#xff1a; 二、刷新页面…...

嵌入式Linux ,QT5 鼠标键盘设备参数指定环境变量的方法

根文件系统中&#xff0c;一般用mdev来管理设备&#xff0c;不像udev方便&#xff0c;有时候在执行rcS脚本的时候因为&#xff0c;太快&#xff0c;有些设备比如鼠标还没在/dev/input中生成设备文件&#xff0c;最好使用前用mdev -s扫描并等待几秒钟&#xff0c;然后就可以在in…...

C语言钥匙迷宫2.0

目录 开头程序程序的流程图程序游玩的效果结尾 开头 大家好&#xff0c;我叫这是我58。废话不多说&#xff0c;咱们直接开始。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <Windows.h> enum color {Y,B,R …...

【多线程】初步认识Thread类及其应用

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 上篇文章我们简单介绍了什么是进程与线程&#xff0c;以及他们之间的区别与联系&#xff0c;实际应用中还是以多线程编程为主的&#xff0c;所以这篇文章就让我们更加深入地去剖…...

algorithm算法库学习之——划分操作和排序操作

algorithm此头文件是算法库的一部分。本篇介绍划分操作和排序操作。 划分操作 is_partitioned (C11) 判断范围是否已按给定的谓词划分 (函数模板) partition 将范围中的元素分为两组 (函数模板) partition_copy (C11) 复制一个范围&#xff0c;将各元素分为两组 (函数模板) st…...

XSS实验记录

目录 XXS地址 实验过程 Ma Spaghet Jeff Ugandan Knuckles Ricardo Milos Ah Thats Hawt Ligma Mafia Ok, Boomer XXS地址 XSS Game - Learning XSS Made Simple! | Created by PwnFunction 实验过程 Ma Spaghet 要求我们弹出一个alert(1337)sandbox.pwnfuncti…...

Cortex-A7的GIC(全局中断控制器)使用方法(7):基于stm32MP135的GIC配置中断效果测试

0 参考资料 STM32MP13xx参考手册.pdf&#xff08;RM0475&#xff09; ARM Generic Interrupt Controller Architecture version 2.0 - Architecture Specification.pdf 1 GIC配置中断效果测试 前面我们已经实现了GIC的配置&#xff0c;为了验证GIC是否配置有效&#xff0c;本例…...

c++动态数组new和delete

文章目录 动态数组的使用大全1. **基本创建和初始化**2. **动态调整大小**3. **动态数组的使用与标准库 std::vector**4. **动态数组作为函数参数**输出 5. **使用动态数组存储用户输入** 动态数组的使用大全 1. 基本创建和初始化 示例&#xff1a; #include <iostream&g…...

Redis热点知识速览(redis的数据结构、高性能、持久化、主从复制、集群、缓存淘汰策略、事务、Pub/Sub、锁机制、常见问题等)

Redis是一个开源的、使用内存作为存储的、支持数据结构丰富的NoSQL数据库。它的高性能、灵活性和简单易用使其在许多场景下成为首选的缓存解决方案。以下是Redis的常见和热点知识总结。 数据结构 Redis支持五种基本数据结构&#xff1a; String&#xff1a;字符串是Redis中最…...

【C++浅析】lambda表达式:基本结构 使用示例

基本结构 [捕获列表](参数列表) -> 返回类型 { // 函数体 } 捕获列表 ([ ]): 用于指定外部变量的捕获方式。可以&#xff1a; 通过值捕获&#xff1a;[x]通过引用捕获&#xff1a;[&x]捕获所有变量通过值&#xff1a;[]捕获所有变量通过引用&#xff1a;[&]自…...

利用Redis获取权限的多种方式

更多实战内容&#xff0c;可前往无问社区查看http://www.wwlib.cn/index.php/artread/artid/10333.html Redis是我们在实战中经常接触到的一款数据库&#xff0c;因其在前期打点中被利用后可直接影响服务器安全所以在攻防过程中也备受红队关注&#xff0c;在本文中会重点分享一…...