【FPGA】AXI4-Lite总线读写BRAM

article/2025/10/9 11:18:44

博主参考和学习的博客

  1. AXI协议基础知识 。这篇博客比较详细地介绍了AXI总线,并且罗列了所有的通道和端口,写代码的时候可以方便地进行查表。
  2. AXI总线,AXI_BRAM读写仿真测试 。 这篇文章为代码的书写提供大致的思路,比如状态机和时序的控制问题,可以参考。

valid-ready双向握手机制

  1. 双向握手机制的实质是:
    数据接收方R告诉数据发送方T“我准备好接收数据了”,并拉高ready;同样的,数据发送方T告诉数据接收方R“我准备好发送数据了”,并拉高valid。

数据发送方给出valid,数据接收方给出ready

  1. 重点:只有在valid和ready同时拉高时,表面成功握手,数据才得以传输。
    【例】比如下图,当前clk上升沿检测到awvalid和awready都拉高,aw握手成功,此时32位的awaddr地址得以写入bram。
    在这里插入图片描述
    【例】比如下图,当前clk上升沿检测到wvalid和wready都拉高,w握手成功,此时32位的wdata数据得以写入bram。
    在这里插入图片描述

  2. 读写BRAM需要用到四个的AXI通道。每一个通道下都有很多端口,包括常规的数据线和valid-ready线
    ① 写地址通道AW(address write)

//写地址通道AW
reg [31:0]  awaddr;    //in(视角:bram)
reg         awvalid;   //in
wire        awready;   //out

② 写数据通道W(write)

//写数据通道W
reg [31:0]  wdata;     //in
reg         wvalid;    //in
wire        wready;    //out
reg [3:0]   wstrb;     //in

③ 写响应通道B

//写响应通道B
reg         bready;    //in:表示主机准备好接收bram的数据
wire        bvalid;    //out:表示bram可以给master发送数据
wire [1:0]  bresp;     //out

④ 读地址通道AR(address read)

//读地址通道AR
reg [31:0]  araddr;    //in
reg         arvalid;   //in
wire        arready;   //out

⑤ 读数据通道R(read)

//读数据通道R
wire [31:0] rdata;     //out
wire        rvalid;    //out
reg         rready;    //in
wire [1:0]  rresp;     //out

博主画了一张图方便理解和查询:
在这里插入图片描述

这是BRAM的IP核设置界面,可以清晰地看到各个通道。
在这里插入图片描述


突发读和突发写时序


有关AXI进行BRAM读写的细节问题

【主从valid-ready互不干扰】
正常工作情况下valid不等待ready,ready也不等待valid。因为主机和从机的逻辑判断是独立的,都是根据自己的情况拉高valid或者ready,换句话说就是:“主机想发数据就把自己的valid拉高,从机能接收数据就把自己的ready拉高”。正好握上了数据就开始传。

【有一边出现繁忙,才会出现等待握手的情况】
如果现在主机可以发送数据,拉高了valid,但是从机处于繁忙状态不能接收数据,没有拉高ready。这个时候主机valid信号就要等待从机退出繁忙并将ready拉高。


代码详解

我们书写代码,是站在“主机master”的视角,去操控bram的。

我们的程序中关于valid-ready双向握手协议的部分,只需要操纵主机的三个valid信号(awvalid,wvalid,arvalid)和一个ready信号(rready),从机bram的ready不需要我们操心。如果主从握手成功,数据便会成功传输,即对于数据传输的过程只要握手成功便会进行,也不需要我们操心。

  1. 状态机——状态空间:
    由于AXI读写时序较为复杂,为了更加好地操控时序和debug,博主使用状态机进行书写。
reg [3:0]   STATE;
parameter   wr_addr             = 4'b0000;
parameter   wr_addr_shakehand   = 4'b0001;
parameter   wr_data             = 4'b0010;
parameter   wr_data_shakehand   = 4'b0011;
parameter   write               = 4'b0100;          
parameter   rd_addr             = 4'b0101;
parameter   rd_addr_shakehand   = 4'b0110;
parameter   rd_data             = 4'b0111;
parameter   rd_data_shakehand   = 4'b1000;
parameter   read                = 4'b1001;
parameter   init                = 4'b1010;
parameter   buffer              = 4'b1011;
parameter   stop                = 4'b1111;
  1. 状态机——状态跳转:
always@(posedge clk or negedge rst_n)
beginif(!rst_n)    STATE <= init;else    begincase(STATE)init:   beginif(init_cnt == 5)   STATE <= wr_addr;else            STATE <= init;                    endwr_addr:            STATE <= wr_addr_shakehand;wr_addr_shakehand:  beginif(awvalid == 1'b1 && awready == 1'b1)  STATE <= wr_data;else                                STATE <= wr_addr_shakehand;     endwr_data:            STATE <= wr_data_shakehand;wr_data_shakehand:  beginif(wvalid == 1'b1 && wready == 1'b1)    STATE <= write;else                                STATE <= wr_data_shakehand;endwrite:              STATE <= buffer;buffer:             STATE <= rd_addr;rd_addr:            STATE <= rd_addr_shakehand;rd_addr_shakehand:  beginif(arvalid == 1'b1 && arready == 1'b1)  STATE <= rd_data;else                                STATE <= rd_addr_shakehand;endrd_data:            STATE <= rd_data_shakehand;rd_data_shakehand:  beginif(rready == 1'b1 && rvalid == 1'b1)    STATE <= read;else                                STATE <= rd_data_shakehand;endread:               STATE <= stop;stop:               STATE <= stop;default:           STATE <= init;endcaseend    
end
  1. 写地址通道AW:

① 给出要写入的地址ADDRESS,并将awvalid拉高,等待bram拉高awready进行握手。
(准确来说不是等待,因为bram只要满足条件就会拉高awready,主从逻辑独立。此处为方便表达。)
② awvalid-awready握手后,数据awaddr传输完成,此时主机要主动拉低awvalid。

//写地址通道AW
parameter   ADDRESS = 114;
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginawaddr  <= 32'b0;awvalid <= 1'b0;end     else if(STATE == wr_addr)    beginawaddr <= ADDRESS;awvalid <= 1'b1;endelse    beginawaddr <= awaddr;awvalid <= awvalid;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == wr_addr_shakehand)  beginif(awvalid == 1'b1 && awready == 1'b1)  beginawvalid <= 1'b0;     //成功握手,valid拉低awaddr <= 32'b0;endend
end
  1. 写数据通道W:

① 给出要写入的数据WR_DATA,同时拉高wvalid,等待bram拉高wready进行握手
② wvalid-wready握手后,数据wdata传输完成,此时主机要主动拉低wvalid。
③ 对于wstrb,在数据传输时赋为 4’b1111,表示wdata32位数据均有效。
(wstrb:写数据有效的字节线,用来表明哪8bits数据是有效的。)

//写数据通道W
parameter   WR_DATA = 514;
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginwdata <= 32'b0;wvalid <= 1'b0;wstrb <= 4'b0;endelse if(STATE == wr_data)   beginwdata <= WR_DATA;wvalid <= 1'b1;wstrb <= 4'b1111;end    else    beginwdata <= wdata;wvalid <= wvalid;wstrb <= wstrb;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == wr_data_shakehand)   beginif(wvalid == 1'b1 && wready == 1'b1)    beginwvalid <= 1'b0;wstrb  <= 4'b0000;wdata  <= 0;endelse    beginwvalid <= wvalid;wstrb <= wstrb;endend
end
  1. 写响应通道B:

在AXI-Lite中,我们只需要管bready这一个端口就行。我们只需要一直拉高bready就行。
(bready:主机接受响应就绪信号 。该信号表示主机是否能够接受响应信息。1 = 主机就绪,0 = 主机未就绪。)
对于bvalid和bresp不需要我们操心,因为那是bram给到主机的,不由我们控制。

//写响应通道B
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginbready <= 1'b1;endelse if(STATE == write || STATE == read)  beginbready <= 1'b1;end
end
  1. 读地址通道AR:

① 给出要读取的地址ADDRESS,并将arvalid拉高,等待bram拉高arready进行握手。
② arvalid-arready握手后,数据araddr传输完成,此时主机要主动拉低arvalid。

//读地址通道AR
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginaraddr <= 32'b0;arvalid <= 1'b0;endelse if (STATE == rd_addr)  beginaraddr <= ADDRESS;arvalid <= 1'b1;endelse    beginaraddr <= araddr;arvalid <= arvalid;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == rd_addr_shakehand)  beginif(arvalid == 1'b1 && arready == 1'b1)  beginarvalid <= 1'b0;endelse    arvalid <= arvalid;end
end
  1. 读数据通道R:

① 将rready拉高,等待bram拉高rvalid进行握手。
② rready-rvalid握手后,数据rdata传输完成,此时主机要主动拉低rready。
(注意:此时的数据流向是bram→主机,因此主机端为ready信号,bram端为valid信号。)

//读数据通道R
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginrready <= 1'b0;endelse if(STATE == rd_data)    beginrready <= 1'b1;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == rd_data_shakehand)  beginif(rready == 1'b1 && rvalid == 1'b1)    beginrready <= 1'b0;endelse    rready <= rready;end
end
  1. 实例化block memory generator IP核模块:
blk_mem_gen_0   mybram(.s_aclk(clk),.s_aresetn(rst_n),.s_axi_awaddr(awaddr),.s_axi_awvalid(awvalid),.s_axi_awready(awready),.s_axi_wdata(wdata),.s_axi_wvalid(wvalid),.s_axi_wready(wready),.s_axi_wstrb(wstrb),.s_axi_bready(bready),.s_axi_bvalid(bvalid),.s_axi_bresp(bresp),.s_axi_araddr(araddr),.s_axi_arvalid(arvalid),.s_axi_arready(arready),.s_axi_rready(rready),.s_axi_rvalid(rvalid),.s_axi_rdata(rdata));

完整代码(包含Testbench)

module axi4_light_bram(
input   wire    clk,
input   wire    rst_n);reg [3:0]   STATE;
parameter   wr_addr             = 4'b0000;
parameter   wr_addr_shakehand   = 4'b0001;
parameter   wr_data             = 4'b0010;
parameter   wr_data_shakehand   = 4'b0011;
parameter   write               = 4'b0100;          
parameter   rd_addr             = 4'b0101;
parameter   rd_addr_shakehand   = 4'b0110;
parameter   rd_data             = 4'b0111;
parameter   rd_data_shakehand   = 4'b1000;
parameter   read                = 4'b1001;
parameter   init                = 4'b1010;
parameter   buffer              = 4'b1011;
parameter   stop                = 4'b1111;//写地址通道AW
reg [31:0]  awaddr;    //in(视角:bram)
reg         awvalid;   //in
wire        awready;   //out
//写数据通道W
reg [31:0]  wdata;     //in
reg         wvalid;    //in
wire        wready;    //out
reg [3:0]   wstrb;     //in
//写响应通道B
reg         bready;    //in:表示主机准备好接收bram的数据
wire        bvalid;    //out:表示bram可以给master发送数据
wire [1:0]  bresp;     //out
//读地址通道AR
reg [31:0]  araddr;    //in
reg         arvalid;   //in
wire        arready;   //out
//读数据通道R
wire [31:0] rdata;     //out
wire        rvalid;    //out
reg         rready;    //in
wire [1:0]  rresp;     //out//初始缓冲init
reg [3:0] init_cnt;
always@(posedge clk or negedge rst_n)
beginif(!rst_n) init_cnt <= 0;else    init_cnt <= (init_cnt == 5) ? 0 : (init_cnt + 1);
endalways@(posedge clk or negedge rst_n)
beginif(!rst_n)    STATE <= init;else    begincase(STATE)init:   beginif(init_cnt == 5)   STATE <= wr_addr;else            STATE <= init;                    endwr_addr:            STATE <= wr_addr_shakehand;wr_addr_shakehand:  beginif(awvalid == 1'b1 && awready == 1'b1)  STATE <= wr_data;else                                STATE <= wr_addr_shakehand;     endwr_data:            STATE <= wr_data_shakehand;wr_data_shakehand:  beginif(wvalid == 1'b1 && wready == 1'b1)    STATE <= write;else                                STATE <= wr_data_shakehand;endwrite:              STATE <= buffer;buffer:             STATE <= rd_addr;rd_addr:            STATE <= rd_addr_shakehand;rd_addr_shakehand:  beginif(arvalid == 1'b1 && arready == 1'b1)  STATE <= rd_data;else                                STATE <= rd_addr_shakehand;endrd_data:            STATE <= rd_data_shakehand;rd_data_shakehand:  beginif(rready == 1'b1 && rvalid == 1'b1)    STATE <= read;else                                STATE <= rd_data_shakehand;endread:               STATE <= stop;stop:               STATE <= stop;default:           STATE <= init;endcaseend    
end//写地址通道AW
parameter   ADDRESS = 114;
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginawaddr  <= 32'b0;awvalid <= 1'b0;end     else if(STATE == wr_addr)    beginawaddr <= ADDRESS;awvalid <= 1'b1;endelse    beginawaddr <= awaddr;awvalid <= awvalid;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == wr_addr_shakehand)  beginif(awvalid == 1'b1 && awready == 1'b1)  beginawvalid <= 1'b0;     //成功握手,valid拉低awaddr <= 32'b0;endend
end//写数据通道W
parameter   WR_DATA = 514;
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginwdata <= 32'b0;wvalid <= 1'b0;wstrb <= 4'b0;endelse if(STATE == wr_data)   beginwdata <= WR_DATA;wvalid <= 1'b1;wstrb <= 4'b1111;end    else    beginwdata <= wdata;wvalid <= wvalid;wstrb <= wstrb;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == wr_data_shakehand)   beginif(wvalid == 1'b1 && wready == 1'b1)    beginwvalid <= 1'b0;wstrb  <= 4'b0000;wdata  <= 0;endelse    beginwvalid <= wvalid;wstrb <= wstrb;endend
end//写响应通道B
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginbready <= 1'b1;endelse if(STATE == write || STATE == read)  beginbready <= 1'b1;end
end//读地址通道AR
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginaraddr <= 32'b0;arvalid <= 1'b0;endelse if (STATE == rd_addr)  beginaraddr <= ADDRESS;arvalid <= 1'b1;endelse    beginaraddr <= araddr;arvalid <= arvalid;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == rd_addr_shakehand)  beginif(arvalid == 1'b1 && arready == 1'b1)  beginarvalid <= 1'b0;endelse    arvalid <= arvalid;end
end//读数据通道R
always@(posedge clk or negedge rst_n)
beginif(!rst_n) beginrready <= 1'b0;endelse if(STATE == rd_data)    beginrready <= 1'b1;end
end
always@(posedge clk or negedge rst_n)
beginif(STATE == rd_data_shakehand)  beginif(rready == 1'b1 && rvalid == 1'b1)    beginrready <= 1'b0;endelse    rready <= rready;end
endblk_mem_gen_0   mybram(.s_aclk(clk),.s_aresetn(rst_n),.s_axi_awaddr(awaddr),.s_axi_awvalid(awvalid),.s_axi_awready(awready),.s_axi_wdata(wdata),.s_axi_wvalid(wvalid),.s_axi_wready(wready),.s_axi_wstrb(wstrb),.s_axi_bready(bready),.s_axi_bvalid(bvalid),.s_axi_bresp(bresp),.s_axi_araddr(araddr),.s_axi_arvalid(arvalid),.s_axi_arready(arready),.s_axi_rready(rready),.s_axi_rvalid(rvalid),.s_axi_rdata(rdata));endmodule

Testbench如下:

`timescale 1ns / 1ps
module axi4_light_bram_tb();reg clk;
reg rst_n;initial beginclk = 1'b0;rst_n = 1'b0;#150rst_n = 1'b1; 
endalways # 10  clk <= ~clk;axi4_light_bram axi4_light_bram_uut(.clk(clk),.rst_n(rst_n)
);endmodule

仿真结果分析

在这里插入图片描述


心得和后续工作

  1. AXI总线算是比较复杂的总线,虽然后续开发的过程中大多不需要自己去写读写时序,但是经过这么一个过程能加深我对AXI协议的理解。“握手”是协议的精髓所在,它有效地控制着整个时序,并且保证主从机互相了解对方的状态,方便数据传输的开始和终止。
  2. 本程序只是最简单的AXI-Lite,如果书写常规的AXI协议,将多出一些端口需要配置(比如id,len,size),后续博主会在这个代码的基础上写常规AXI协议。
  3. 本程序只进行了一次数据的读和写。但是使用AXI协议可以同时写很多数据,然后用last指示最后一个数据,此类云云。后续我会去写这样的代码的。

http://chatgpt.dhexx.cn/article/jUE39KeX.shtml

相关文章

如何对bram/ram进行初始化赋值呢?

1、首先对于常规的情况&#xff0c;即加载.coe文件的方式实现初始化&#xff08;与rom相同&#xff09; 点击load initial file, 在右侧可以直接添加.coe文件&#xff0c;或者选择edit进行手动编辑&#xff08;数据量不大的情况下可选&#xff0c;但是不推荐&#xff09;&#…

vivado中bram的种类与使用

vivado中bram的种类与使用 vivado中bram的分类单端口ram初始化工作时序仿真验证 简化的双端口RAM初始化端口定义仿真结果 双端口RAM初始化端口定义功能仿真单端口读数双端口读数双端口一读一写双端口写数据 vivado中bram的分类 在vivado中打开IP catalog&#xff0c;在其中搜索…

BRAM的使用

使用Block Memory Generator IP核&#xff0c;PL读取BRAM数据 软件环境&#xff1a;Vivado 2018.3 IP核&#xff1a;Block Memory Generator 8.4(Rev.2) 1、点击IP Catalog 2、搜索”Block Memory Generator“双击选择RAMs & ROMs & BRAM下的IP核 3、配置IP核为Si…

FPGA — BRAM学习笔记—读写操作

使用软件&#xff1a; Vivado 开发板&#xff1a; EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA BRAM笔记 BRAM介绍同步双端口BRAMBRAM读写操作(1)读操作(2)写操作(3)写模式写优先模式读优先模式不变模式 双端口块内存接口BRAM IP的使用及仿真验证IP核使用coe文件将IP核添…

FPGA从入门到精通(8)-BRAM

所使用EDA软件&#xff1a;VIVADO2018.3 FPGA型号&#xff1a;xc7a35tcsg325-2 很久没写了&#xff0c;随便写一篇BRAM的吧。说到BRAM &#xff0c;很多人都喜欢拿它来DRAM比较 &#xff0c;两者都有啥优缺点&#xff0c;其实我也拿不准。不过一般来说&#xff0c;存储较大的数…

Xilinx系列学习(一) BRAM的使用,并用PL读取BRAM数据

Xilinx系列学习(一) BRAM的使用,并用PL读取BRAM数据 一,Xilinx BRAM介绍二,BRAM对应的IP核调用和使用1,BRAM对应的IP核介绍2,BMG例化IP核的调用一,Xilinx BRAM介绍 BRAM 就是Block Memory,是Zynq的PL端的存储RAM单元。可以利用BRAM,在PS和PL之间进行数据的交换。Zyn…

FPGA设计中BRAM(Block RAMs)资源的使用(综合为BRAM)

FPGA设计中BRAM&#xff08;Block RAMs&#xff09;资源的使用 RAM分为BRAM&#xff08;Block RAMs&#xff09;和DRAM&#xff08;Distributed RAM&#xff09;&#xff0c;即块RAM与分布式RAM&#xff0c;这两个差别在于BRAM是FPGA上固有的一些存储资源&#xff08;针对不同型…

web测试与app测试的区别

目录 前言 首先从系统架构来看 专项测试 安装、卸载、更新&#xff1a; 界面操作&#xff1a; 前言 仅仅从功能测试的层面上来讲的话&#xff0c;在流程和功能测试上是没有区别的。那么区别在哪里呢&#xff1f; 我个人觉得就是由于载体不一样&#xff0c;所以系统测试和…

APP测试与WEB测试

APP测试与WEB测试的区别(异同) 相同点&#xff1a; 功能测试层面而言&#xff1a;APP测试和web测试都是使用相同的测试用例测试方法&#xff08;都用到等价类划分、边界值分析、正常和异常情况去考虑测试点&#xff09; UI界面测试&#xff1a;都需要按照原型图和设计图检查UI…

web测试,App测试,小程序测试区别

最近项目真的太忙了&#xff0c;不过&#xff0c;今天无论如何我都要更文章了&#xff0c;谢谢大家的支持&#xff0c;不断努力进步 这篇文章&#xff0c;我就是要梳理一下&#xff0c;web测试&#xff0c;app测试&#xff0c;和小程序的区别 话不多说&#xff0c;上主题 web…

WEB端与移动端测试区别和总结

WEB端与移动端测试区别总结如下&#xff1a; 1、系统架构 WEB端 B/S结构&#xff0c;WEB端的前端一般不做端的区分 WEB端的上线不管是预发布还是N环上线&#xff0c;server上线后&#xff0c;前端同步更新&#xff0c;一般是不存在多个版本的问题; 移动端 C/S结构&#xff0c;移…

Apifox简单了解——WEB端测试的集大成者

文章目录 0 引入1、Postman2、Swagger &#xff08;丝袜哥&#xff09;3、Mock4、JMeter5、Apifox6、引用 0 引入 Apifox Postman Swagger Mock JMeter 1、Postman 1 作用 Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件&#xff0c;简单易用的接口测试…

web测试的基本流程

1、web测试流程&#xff1a; (1)web测试 1)参与一个web新项目的测试前&#xff0c;先搜集测试相关的资料&#xff0c;包括原型图、各种需求文档、业务相关等需求相关材料 2)结合第一步搜集到的需求相关资料&#xff0c;自行熟悉系统&#xff0c;同时列出不明白的点&#xff0c;…

Web端测试常用方法

介绍下工作中&#xff0c;Web端测试所涉及到的方法&#xff1a; 前言&#xff1a;Web测试常用的方法&#xff0c;兼容性测试、安全性测试、可用性测试 & 逻辑功能测试 1 > 兼容性测试 先说下兼容性测试&#xff0c;工作中在测试时&#xff0c;一般涉及操作系统测试、浏…

web端测试经验(项目实战经验)

软件测试相信大家已经有一定的了解了&#xff0c;无非就是找bug 找缺陷 找问题 找这个程序&#xff08;前端、后端&#xff09;的不足点 以及不人性化的地方 &#xff0c;由我们监测并提出有效的建议给项目进行缺陷修复以及优化点。软件测试大体分为Web、App两个&#xff0c;当…

这可能是最全的Web测试各个测试点,有这一篇就够了

前言 什么是Web测试&#xff1f; Web测试测试Web或Web应用程序的潜在错误。它是在上线前对基于网络的应用程序进行完整的测试。 Web测试检查 功能测试 易用性测试 接口测试 性能测试 安全测试 兼容性测试 1、功能测试 测试网页中的所有链接、数据库连接、网页中用于提交或从…

【转载】 web项目测试

前言 之前说了APP项目的测试&#xff0c;今天来总结一下web项目的测试&#xff0c;其实大多数过程是差不多类似的。对比平常移动端手机的高频率使用来说&#xff0c;对于部分人使用pc端浏览器的概率就不会这么高&#xff0c;讲APP项目测试的时候没怎么涉及到网络协议部分的介绍…

Web端测试方法

web端通用测试点请移步 1. Web 测试的总体策略 2. Web 测试的范围 √ 功能 √ 性能 √ 界面 √ 兼容性 √ 安全性 √ DB √ 文档 2.1 功能测试 ☆ 功能测试主要从链接、表单、Cookies、设计语言、数据库、文件上传等方面进行。 2.1.1 链接 ☆ 链接也称超链接&#xff0c;…

Redis集群 关闭和重启

1、创建好的redis集群&#xff0c;一下是正常运行的3主3从服务器 2、正常关闭集群服务器 [rootca01 redis-cluster]# cat stopall.sh cd 7001 ./redis-cli -p 7001 shutdown cd .. cd 7002 ./redis-cli -p 7002 shutdown cd .. cd 7003 ./redis-cli -p 7003 shutdown cd .. c…

叫你别随便重启Redis!!!怎么样,数据全丢了吧~~~

目录 事情是这样的... Redis持久化数据的两种模式 一、RDB模式 二、AOF模式 三、RDB和AOF之间的关系 四、问题回顾分析 那么该如何开启AOF增量备份模式呢&#xff1f; 解决方法: 1、登录到redis 2、在线修改AOF开关 3、查看数据 事情是这样的... 今天&#xff0c;跑…