顶端(最快,最小)
┌─────────────────┐
│ CPU寄存器 │ ← 纳秒级,KB级别
├─────────────────┤
│ CPU缓存(L1-L3) │ ← 纳秒级,几十KB到几十MB(相联存储器在这里)
├─────────────────┤
│ 内存(RAM) │ ← 百纳秒级,GB级别(虚拟内存在这里)
├─────────────────┤
│ 固态硬盘(SSD) │ ← 微秒级,百GB到TB级(DMA参与搬运)
├─────────────────┤
│ 机械硬盘(HDD) │ ← 毫秒级,TB级(RAID在这里组织磁盘)
└─────────────────┘
底端(最慢,最大)存储体系:一条数据从硬盘到CPU的流水线
整个存储体系可以理解为一条数据传送带,目标是:让CPU尽可能快地拿到要处理的数据
第一级:硬盘 —— 数据的仓库
它是谁:机械硬盘(磁盘)或固态硬盘。
干什么:永久保存数据。关机不会丢。
怎么干:
机械硬盘:用磁头读写磁盘表面的磁性方向(南极/北极代表0/1)。
固态硬盘:用电压控制晶体管的电子数量(有电子/没电子代表0/1)。
特点:容量大,价格便宜,但极慢(比内存慢几万倍)。
第二级:内存 —— 数据的工作台
它是谁:内存条(DRAM)。
干什么:临时存放正在运行的程序和数据。关机就丢。
怎么干:用电容里有没有电荷(有电/没电)来存0/1。
特点:比硬盘快得多,但比CPU还是慢得多,而且断电消失。
问题:硬盘到内存太慢,谁搬?
DMA(直接内存访问):
它是谁:一个专门的硬件搬运工(集成在CPU或主板芯片里)。
干什么:负责硬盘和内存之间的数据搬运。
怎么干:CPU告诉它“去搬什么、搬到哪”,然后它自己搬,搬完通知CPU。搬运期间CPU可以干别的活。
第三级:缓存 —— 数据的桌面
它是谁:CPU内部的极快小容量存储器(SRAM)。
干什么:存放CPU马上要用的数据副本(从内存复制来的)。
怎么干:
映射方式:决定内存里的数据可以放在缓存的哪个位置。
直接映射:每个数据只能去一个固定位置(简单但冲突多)。
全相联映射:任何数据可以放任何位置(灵活但查找复杂)。
组相联映射:先分组,组内随便放(折中方案,实际在用)。
替换策略:缓存满了,新数据进来要赶走谁。
LRU(最近最少用):赶走最久没被访问的那个。
查找方式:用地址的一部分快速定位到可能的位置,然后比较确认。
为什么快:因为局部性原理——程序访问数据有惯性,刚用过的附近数据很可能马上再用。
第四级:寄存器 —— 手心里的数据
它是谁:CPU内部最顶层的存储单元。
干什么:存放CPU当前正在计算的值。
怎么干:直接参与运算,比如 a = b + c,b和c就在寄存器里,结果也放寄存器。
特点:速度极快,容量极小(几十到几百字节)。
存储体系的扩展:多块硬盘怎么协作?—— RAID
把多块硬盘组合起来,要么为了更快,要么为了更安全,或者两者兼顾。
整个流程串起来
1.CPU发出请求:带着一个逻辑地址(程序眼里的地址)。
2.地址翻译:MMU拿着这个逻辑地址,先查TLB(那个用相联存储器做的快表)。如果TLB命中:瞬间拿到物理地址。如果TLB没命中:去内存里的页表查,查到后更新TLB。
3.查缓存:拿着物理地址,去CPU缓存里找。
怎么找:根据映射方式(比如组相联),计算出可能在哪个组,然后遍历组内的几个缓存行(相联比较),看标签是否匹配。
如果缓存命中:数据直接从缓存返回CPU。快!
如果缓存未命中:缓存控制器拿着同一个物理地址,去内存里取。
4.内存访问:
如果数据在内存里:内存控制器把数据返回给CPU,同时写入缓存(方便下次用)。
如果数据不在内存里(比如还没从硬盘加载):触发缺页中断。
5.硬盘读取(DMA登场):
操作系统启动DMA控制器,让它把数据从硬盘搬到内存。
DMA搬运期间,CPU可以干别的活。
搬完后,DMA通知CPU:"数据好了!"
6.重新来过:CPU再次发起访问,这次数据已经在内存里了,会经历缓存未命中→从内存读→写入缓存的过程。
7.如果用了RAID:硬盘层面,文件可能被拆成多块存在不同硬盘上(RAID 0),或者有备份(RAID 1),但CPU和操作系统感知不到,它只看到一块"虚拟磁盘"。
2.流水线技术:理解流水线的基本概念,能计算流水线的周期、吞吐率及加速比 。
流水线周期:也叫流水线时钟周期,就是最慢的那个阶段需要的时间。因为整个流水线是按统一的时钟节拍推进的,每个阶段必须在规定时间内完成,所以周期取决于最慢的那一段。
周期 = max(各阶段时间)
比如某指令流水线有 5 个阶段,时间分别为:取指 10ns,译码 8ns,执行 12ns,访存 10ns,写回 7ns。那么周期 = max(10,8,12,10,7) = 12ns。
吞吐率:单位时间内完成的任务数量。在计算机里,吞吐率就是每秒完成的指令数(IPS,instructions per second)或百万条指令每秒(MIPS)。
理想情况下,流水线稳定后,每个时钟周期完成一条指令(假设无停顿)。
吞吐率 = 1 / 周期。
如上例,吞吐率 = 1 / 12ns ≈ 83.3 MIPS(百万条指令/秒)。
实际中会有停顿(比如数据依赖、分支预测失败),所以实际吞吐率会低一些。
加速比:使用流水线比不用流水线快了多少倍。公式是:
加速比=不使用流水线的总时间/使用流水线的总时间
流水线就是把指令切成多段,让不同指令的段重叠执行,用最慢的那段决定周期,稳定后每个周期完成一条,理论上比串行快接近段数倍。
3.性能指标与可靠性:掌握主频、CPI、MIPS等关键性能指标的计算方法。理解串联与并联系统的可靠性模型,这是评估高可用数据库集群的基础
- 主频(时钟频率)
定义:CPU每秒产生的时钟脉冲数,单位是赫兹(Hz)。比如3.0GHz表示每秒30亿个时钟周期。
通俗理解:可以看作是CPU的“心跳”速度,心跳越快,CPU可能工作得越快,但并不是唯一决定因素。
作用:主频决定了每个时钟周期的时间长度:T=1/f。如果主频3GHz,一个时钟周期 ≈ 0.33纳秒。 - CPI(Cycle Per Instruction,每条指令需要的时钟周期数)
定义:执行一条指令平均需要的时钟周期个数。
通俗理解:不同指令的复杂度不同,有的指令需要1个周期(比如简单加法),有的可能需要多个周期(比如除法、内存访问)。CPI就是平均下来每条指令消耗的周期数。
影响因素:CPU架构、指令集、流水线效率、缓存命中率等。通常CPI越小越好。 - MIPS(Million Instructions Per Second,每秒百万条指令)
定义:每秒能执行的指令数量,以百万条为单位。
计算公式:
MIPS=主频(MHz)/CPI
因为主频单位是MHz(百万赫兹),CPI是每条指令周期数,两者相除就得到每秒百万条指令。
例子:一个CPU主频3.0GHz(3000MHz),平均CPI=1.5,则MIPS = 3000 / 1.5 = 2000 MIPS,即每秒可执行20亿条指令。 - 它们之间的关系
程序执行时间 = 指令总数 × CPI × 时钟周期时间 或= 指令总数 × CPI / 主频
MIPS 是衡量性能的一个粗略指标,但不同指令集之间比较MIPS可能不准确(因为不同架构的一条指令能干的事不同)。不过在同一架构下,MIPS越高性能越好。 - 实际应用:如何用这些指标评估系统?
在设计数据库服务器时,需要估算CPU能否处理预期的事务负载。比如某个数据库操作平均需要10万条指令,每秒有1万次事务,那么需要的处理能力 = 10万 × 1万 = 10^9 条指令/秒 = 1000 MIPS。如果CPU的MIPS大于这个值,理论上可以满足,还要考虑其他瓶颈。
- 串联系统
定义:多个部件必须全部正常工作,整个系统才能正常工作。比如一台服务器需要电源、主板、CPU都正常才能运行,任何一个坏了,系统就宕机。
可靠性公式:
特点:部件越多,可靠性越低。因为相乘会使可靠度下降。
例子:一个服务器由三个部件串联,可靠度分别为0.99、0.999、0.999,则系统可靠度 = 0.99×0.999×0.999 ≈ 0.988,低于最差部件。
- 并联系统
定义:多个部件至少有一个正常工作,系统就能正常工作。也就是冗余备份。比如两台数据库服务器做双机热备,一台坏了另一台接管。
可靠性公式:
特点:冗余越多可靠性越高,但成本增加。
例子:一个部件可靠度0.9,两个并联:系统可靠度 = 1 - 0.1×0.1 = 0.99。比单个的0.9高。
- 混合系统
实际系统往往是串联和并联的组合。比如数据库集群中,多个节点并联提供高可用,但每个节点内部又是串联的(电源、CPU等)。
- 性能指标的应用
容量规划:根据业务预估的每秒事务数(TPS),每个事务的指令数,计算出需要的MIPS,从而选择合适CPU的服务器。
瓶颈分析:如果实际MIPS低于预期,可能CPI过高(比如缓存缺失多),需要优化数据库查询或增加缓存。
横向扩展:集群可以增加节点分担负载,每个节点处理部分请求,整体吞吐量提升。但也要考虑节点间的协调开销。 - 可靠性模型的应用
集群高可用:数据库集群通常采用并联模型:多个节点同时提供服务或主备切换。只要至少一个节点存活,服务就可用。
计算集群可用性:假设每个节点的年可用性为99%(每年约3.65天宕机),两个节点并联的系统可用性 = 1 - (1-0.99)² = 0.9999(每年约52分钟宕机),大大提升。
串联与并联结合:集群的每个节点内部是串联(单点故障),所以需要节点本身有冗余电源等。而节点间是并联,整体可用性由节点数和单节点可用性决定。
N模冗余:数据库可以有多副本(如三副本),只要大多数副本正常就可读写,这是更复杂的并联模型。 - 实际设计考虑
SLA(服务等级协议):要求99.99%可用性,那么需要计算需要多少个节点以及单节点可靠度。
故障转移时间:并联系统的切换时间也会影响实际可用性,但基础模型给出了理论上限。
总结
主频、CPI、MIPS 是描述CPU处理能力的指标,通过它们可以估算系统能否满足性能需求,是数据库服务器选型的基础。
串联/并联可靠性模型 是理解系统冗余的基本工具,是设计高可用数据库集群(如主从、多副本)的理论依据,帮助你计算需要多少备份才能达到目标可用性。
4.寻址方式
简单来说,就是CPU如何找到它要操作的数据。
1. 立即寻址
功能:操作数直接写在指令里,CPU拿来就用。
实现:指令中的操作数字段直接送到运算单元。
例子:指令 MOV R1, #5
CPU执行时,直接将数字5放入寄存器R1,不访问内存。
2. 寄存器寻址
功能:操作数存放在CPU内部的寄存器中。
实现:指令中给出寄存器编号,CPU从对应寄存器读取。
例子:指令 ADD R1, R2
CPU从寄存器R1和R2中取出数值,相加后结果存回R1。
3. 直接寻址
功能:操作数存放在内存的固定地址。
实现:指令中给出内存地址,CPU直接访问该地址。
例子:指令 LOAD R1, 1000
CPU访问内存地址1000,取出数据放入寄存器R1。
4. 寄存器间接寻址
功能:操作数的内存地址存放在寄存器中。
实现:CPU先取寄存器的值作为地址,再访问该地址。
例子:指令 LOAD R1, (R2)
假设R2中存放的是地址2000,CPU先去R2取2000,然后访问内存2000,将数据放入R1。
5. 变址寻址
功能:通过基地址加偏移量计算内存地址。
实现:CPU将基址寄存器的值与指令中的偏移量相加,得到地址后访问内存。
例子:指令 LOAD R1, 100(R2)
假设R2=2000,CPU计算地址=2000+100=2100,访问内存2100,数据放入R1。
6. 基址寻址
功能:程序运行时动态定位,使程序可以在内存任意位置执行。
实现:指令中给出相对地址,CPU将其与基址寄存器相加得到物理地址。
例子:指令 LOAD R1, 50
假设程序基址寄存器=10000,CPU计算地址=10000+50=10050,访问内存10050,数据放入R1。为什么分这么多
根本原因:指令里能写的位数有限,但数据的位置有多种可能。
一条指令通常只有32位或64位,不能把完整的内存地址(也可能是64位)都塞进去。所以需要各种技巧:
教材分这么多种,是为了让你理解不同场景下CPU怎么找到数据。但在硬件层面,它们共用一套地址计算单元:
所有方式最终都归结为:计算出一个有效地址 → 访问内存(如果需要) → 送到寄存器(如果需要)
区别在于:地址来自哪里?是立即数、寄存器、还是两者相加?
所以你可以把它们看作地址来源的组合方式:
理解这些,不是为了让你去控制CPU,而是为了让你能看懂数据库在干什么、诊断它为什么慢、设计出更优的表和查询。
存储分级 → 教材会告诉你:寄存器、缓存、内存、硬盘速度容量不同。
但没告诉你:你写的SQL,没索引的时候要全表扫,就是因为数据在硬盘/内存里分散着,CPU得一遍遍去取,TLB和缓存根本帮不上忙。
缓存映射方式 → 教材会告诉你:直接映射、组相联、全相联。
但没告诉你:数据库的Buffer Pool(缓存池)也是用类似的思想管理数据页的——你要读的数据如果不在缓存里,就得去磁盘读,这就是缓存未命中。
TLB + MMU → 教材会告诉你:地址翻译、快表。
但没告诉你:你查一个大表的时候,如果数据分布太散,TLB这个小本本装不下所有地址映射,就会频繁未命中,数据库就卡了。这就是为什么有时候内存够大也慢。
寻址方式 → 教材会告诉你:立即、直接、间接、变址……
但没告诉你:你写的 WHERE age = 25 能走索引,就是因为数据库可以用“基址+偏移”(变址寻址)快速定位到B+树的叶子节点。而你写 WHERE YEAR(date)=2023 不走索引,就是因为数据库没法用寻址方式直接跳到年份上,只能挨个算。
流水线 → 教材会告诉你:取指、译码、执行、访存、写回,还有加速比。
但没告诉你:数据库里的并行查询、多线程处理,本质上也是在数据层面做“流水线”——一条线程在处理一批数据的同时,另一条线程已经在读下一批了。
状态寄存器(PSW/标志寄存器):记录运算标志位(如进位C、零Z、符号S、溢出V、奇偶P),用于条件判断。
通用寄存器组:暂存操作数或地址,减少内存访问,提升运算速度。
累加器(ACC):临时存放操作数和中间结果,不能长期保存数据。
取指阶段:程序计数器(PC)提供指令地址,从内存取出指令放入指令寄存器(IR)。
译码阶段:控制器分析IR中的指令,确定需要读取哪些通用寄存器或累加器中的数据。
执行阶段:算术逻辑单元(ALU)根据指令对操作数进行计算,结果暂存于累加器(ACC)或通用寄存器中;同时,状态寄存器根据结果设置标志位。
访存阶段:若指令需要读写内存,则地址来自通用寄存器或指令中的地址码,数据可能经过累加器或通用寄存器。
写回阶段:将执行结果写回目标寄存器(通用寄存器或累加器)。
更新PC:顺序执行时PC自动加1;遇到跳转指令则根据条件标志或目标地址修改PC。
评论