JAVA高级工程师--Redis持久化详细版

一、Redis  DB

Redis 数据库的数量在单机和集群模式下有根本性的区别。

1. 单机模式 (Standalone)

在单机模式下,Redis 默认提供 16 个逻辑数据库,索引编号为 0 到 15

  • 选择数据库: 使用 SELECT <index> 命令进行切换。例如,SELECT 0 使用第一个数据库,SELECT 15 使用最后一个数据库。

  • 配置数量: 这个数量可以通过修改 Redis 配置文件 redis.conf 中的 databases 16 指令来增加或减少。

  • 重要特性: 这些数据库是逻辑隔离的。它们在同一个 RDB/AOF 文件中持久化,由同一个 Redis 进程管理,但 KEYSFLUSHDBSWAPDB 等命令只对当前选中的数据库生效。

总结:单机模式默认有 16 个逻辑 DB,可配置。


2. 集群模式 (Cluster)

在官方 Redis Cluster 模式下,只有 1 个数据库,即数据库 0

  • 无法选择: 尝试使用 SELECT 命令选择任何非 0 的数据库都会报错。

  • 设计原因

    1. 简化设计:集群的核心目标是分片(Sharding),将数据分散到多个节点上。如果再支持多个逻辑数据库,会使键分布、故障转移和集群管理变得异常复杂。

    2. 命名空间隔离:在集群中,不同的业务数据应该通过键名前缀(如 user:1001order:5002) 来进行区分和隔离,而不是使用不同的数据库。

总结:集群模式强制使用且只能使用 DB 0。


对比表格

特性单机模式 (Standalone)集群模式 (Cluster)
数据库数量默认 16 个 (0-15),可配置只有 1 个 (DB 0)
SELECT 命令支持,可切换数据库不支持,使用非 0 索引会报错
设计目的逻辑隔离不同应用的数据数据分片与高可用
数据持久化所有 DB 存储在同一个 RDB/AOF 文件每个节点的 DB 0 独立存储
使用建议可用于隔离不同环境/应用的数据必须使用键前缀来隔离数据

二、Redis持久化

1.为什么需要持久化

Redis 是一个基于内存的数据库,所有数据都存储在内存中。这使得它的读写速度极快。然而,内存是易失性的,如果发生服务器断电、崩溃或进程退出,内存中的数据会全部丢失

持久化的目的就是为了解决这个问题:将内存中的数据保存到磁盘等非易失性存储中,以便在 Redis 重启后能够重新加载数据,防止数据丢失。

2.怎么持久化

redis两种持久化机制。这两种机制,其实是快照日志的形式。

(1)快照RDB (Redis Database)

就是当前数据的备份,我可以拷贝到磁盘,也可以拷贝到别的服务器,如此一来,万一现有redis的计算机节点被恶意攻击或者被人删库跑路,那么你的原有数据还是可以恢复的。像你的云服务器也有快照功能,被人攻击以后直接拿来恢复就行。它是一个紧凑的二进制文件(默认名为 dump.rdb)。是全量备份,也是Redis的默认备份方案。当redis恢复的时候会全量的恢复,此时redis处于阻塞状态。

A.优点
  • 全量备份:每隔一段时间备份,全量备份,比较适合做冷备。

  • 性能高:父进程不需要进行任何磁盘 I/O 操作,由子进程负责,对主服务性能影响极小。

  • 文件紧凑:RDB 文件是二进制压缩格式,非常适合灾难恢复备份。灾备简单,可以远程传输到其他服务器

  • 恢复速度快:恢复大数据集时,比 AOF 方式更快。

  • 父子进程相互隔离:子进程备份的时候,主(父)进程的写操作可以和子进程隔离,数据互不影响,保证备份数据的的完整性
B.缺点
  • 可能丢失更多数据:如果在下一次快照之前服务器宕机,从上一次快照之后的所有数据更改都会丢失。

  • fork 可能阻塞:如果数据集非常大,fork 子进程的过程可能会耗时较长,导致服务短暂停顿(毫秒级或秒级)。

  • 子进程内存损耗:子进程会有一定的内存消耗,尤其是当有大量新的写操作涌入的时候,那些都会有额外的内存开支
  • 全量实时备份不适用:由于定时全量备份是重量级操作,所以对于实时备份的业务场景,就不适用了。
C.RDB的保存方式

问题:假设现在是凌晨1点开始备份,由于有时间损耗,01点钟 05分产生了RDB文件保存到磁盘,那么会如下问题:

  • 这个RDB文件的内容是凌晨1点的数据?
  • 这个RDB文件内容是01点钟05分的数据?
  • 这个RDB文件内容是凌晨1点的数据,并且记录了开始 备份到结束(1点到1点05分之间)的数据?

redis有两种保存方式,一个是save命令,一个是bgsave命令

(1)save

备份rdb到磁盘,阻塞当前进程,redis不接受任何写操作,

(2)bgsave

fork(创建)一个新的子进程,子进程把rdb数据写入磁盘,写操作由父进程去处理,两个进程之间数据隔离,所以rdb的数据不会因为有新的写操作而发生变化。

新的子进程指向的缓存数据和redis父进程一致,所以速度很快。(本质是指针,指向地址,而不是复制一个新的数据,所以父进程有新的写操作是写到新的内存地址,而子进程指向的地址不变)


通过 BGSAVE 命令在凌晨 1:00 开始创建的,由于 BGSAVE 是异步操作,它需要 Fork 一个子进程。Fork 操作完成后,子进程会拥有一个与父进程(主Redis进程)在 fork 那一刻完全一致的内存数据副本。子进程随后将这个副本写入 RDB 文件。

因此,RDB 文件的内容是开始执行 BGSAVE 命令后,成功完成 fork 操作那个瞬间的数据。 fork 操作非常快(通常如此),这个时间点非常接近凌晨 1:00,我们可以近似地认为是 1:00 的数据。但从严格的技术上讲,它记录的是 fork 成功那一刻的数据。

所以上面的问题:无论是 SAVE 还是 BGSAVE,RDB 文件都代表了创建过程开始后、某个瞬间的数据。对于配置的定时任务(比如在 crontab 里设置每天 1:00 执行),我们通常会说“这是凌晨 1 点的备份数据”。

提问:既然bgsave这么好用,为啥还设计一个save命令呢?

不论是开发游戏还是普通的项目,肯定会有维护期,那么在维护期的时候,就会用到save,直接阻塞,不让新的数据写入,游戏项目是最常见的,直接停服了,所有玩家等着新版本上线后才能重新进入。

D.RDB 自动保存机制

redis的核心配置有这么一段内容,这个是触发bgsave的条件,他是自动的,满足条件就会执行rdb的备份。(要注意,它是bgsave

  • stop-writes-on-bgsave-error

    • yes:如果save过程出错,则停止写操作
    • no:可能造成数据不一致
  • rdbcompression

    • yes:开启rdb压缩模式
    • no:关闭,会节约cpu性能开支
  • rdbchecksum

    • yes:使用CRC64算法校验对rdb进行数据校验,有10%性能损耗
    • no:不校验
  • dbfilename:rdb的默认名称,可以自定 dump.rdb

(2)日志AOF (Append Only File)

A、解释和特征

AOF其实就类似于我们开发系统的时候用户的操作日志,这里指的是用户的每次写操作日志,比如增加key,修改key以及删除key,这些命令,追加式备份,都会记录下来形成一个日志文件。那么在需要恢复的时候,只需要执行这个日志文件里的所有命令,就能达到恢复数据的目的。以日志的形式记录每一个写操作命令(例如 SETSADDLPUSH),并在 Redis 重启时通过重放这些命令来恢复数据。秒级别备份。

如果追求数据的一致性,RDB会丢失最后一次的备份数据,所以往往会采用AOF来做。AOF丢失的数据会比RDB相对来说少一些。

  • 默认不开启,需要在配置文件中设置 appendonly yes

  • 所有命令追加到 AOF 文件的末尾。redis是先执行写操作指令,随后再把指令追加进aof中,追加的形式是append,一个个命令追加,而不是修改,

  • 随着写入越来越多,AOF 文件会越来越大。Redis 提供了 AOF 重写机制来压缩文件。AOF文件的大小不直接与“时间”挂钩,而是与期间发生的“写操作”的数量和大小挂钩。

  • 从头到尾恢复AOF:redis恢复的时候是读取aof中的命令,从头到尾读一遍,然后数据恢复。

  • redis恢复的时候先恢复aof,如果aof有问题(比如破损),则再恢复rdb

B、优点
  • 数据更安全:根据策略配置,最多丢失一秒的数据(everysec)。所以AOF可以每秒备份一次,使用fsync操作。

  • 可读性:AOF 文件是纯文本格式,便于理解和手动修复(虽然不推荐)。

  • 以log日志形式追加,如果磁盘满了,会执行 redis-check-aof 工具。它的核心功能是检查AOF文件的完整性,并修剪掉末尾不完整或格式错误的数据redis-check-aof --fix 命令修复AOF文件后再重启。
  • 当数据太大的时候,redis可以在后台自动重写aof。当redis继续把日志追加到老的文件中去时,重写也是非常安全的,不会影响客户端的读写操作。
  • AOF 日志包含的所有写操作,会更加便于redis的解析恢复。
C、缺点
  • 文件更大:通常 AOF 文件会比同期的 RDB 文件大。

  • 恢复速度慢:恢复大数据集时,需要重新执行所有命令,比 RDB 方式慢。

  • 性能影响:在写入负载高时,AOF 对性能的影响通常比 RDB 大。针对不同的同步机制,AOF会比RDB慢,因为AOF每秒都会备份做写操作,这样相对与RDB来说就略低。 每秒备份fsync没毛病,但是如果客户端的每次写入就做一次备份fsync的话,那么redis的性能就会下降。

D、AOF大文件问题

假如,假如某一天redis宕机挂了

  • 这个10年的AOF有多大?最大可以占用多少空间?有没有可能达到10来个T,或者更大?

按理说会,如果你吃饱了没事做,就只对某个key,新增,修改,删除,无限次的做这样的操作,持续了十来年,那么这个aof文件会很大,而且都是重复的命令。但是AOF可以压缩重写,使得体积不大。

一个积累了10年、从未进行过重写的AOF文件,对于一个写入频繁的大型系统来说,达到10TB是完全合理的,甚至可能更大。这凸显了定期执行BGREWRITEAOF(通常通过配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size来自动执行)对于Redis生产运维是绝对必要的。放任AOF无限增长是一种运维事故。

  • 恢复10T文件的时候,内存不大会不会溢出?

不会。虽然文件很大,但是有效的命令实际的不会很多。而且可以压缩重写,这样体积不大,读取肯定更加快速。

  • 10T的aof恢复需要多久,有没有可能几个月,甚至1年?

按照现有情况来说,有可能吧。恢复时间极长是肯定的,但“几个月或一年”在典型的服务器硬件上是一个过于极端和悲观的估计。更可能的时间范围是几天到几周,但这完全取决于硬件性能和一个关键因素:AOF文件中的操作类型。在使用了高性能NVMe SSD,并且AOF文件是经过重写、相对精简的情况下,恢复10TB的AOF可能需要几十个小时(2-4天)

以上三点都是aof文件庞大而出现的顾虑,其实aof可以重写,对日志有一个重写机制bgrewriteaof,其实也就是瘦身的作用

E、AOF 重写 (AOF Rewrite)
  • 目的:去除冗余命令,用最小命令集合重建当前数据集状态。例如,对一个 key 先后执行了 100 次 INCR,重写后只需记录一条 SET key 100

  • 触发:手动执行 BGREWRITEAOF 或自动根据配置(auto-aof-rewrite-percentageauto-aof-rewrite-min-size)触发。

  • 过程:与 BGSAVE 类似,也是 fork 一个子进程在后台完成,不会阻塞主进程。

F、同步策略 (appendfsync):这是影响性能和数据安全性的关键配置。

  • always:每个写命令都同步刷写到磁盘。数据最安全,性能最差

  • everysec:每秒同步一次。平衡了性能和安全,是默认推荐配置。最多丢失 1 秒钟的数据。

  • no:由操作系统决定何时同步。性能最好,但数据最不安全

# AOF 默认关闭,yes可以开启
appendonly no# AOF 的文件名
appendfilename "appendonly.aof"# no:不同步
# everysec:每秒备份,推荐使用
# always:每次操作都会备份,安全并且数据完整,但是慢性能差
appendfsync everysec# 重写的时候是否要同步,no可以保证数据安全
no-appendfsync-on-rewrite no# 重写机制:避免文件越来越大,自动优化压缩指令,会fork一个新的进程去完成重写动作,新进程里的内存数据会被重写,此时旧的aof文件不会被读取使用,类似rdb
# 当前AOF文件的大小是上次AOF大小的100% 并且文件体积达到64m,满足两者则触发重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

但是这个64MB如何确认了,万一瘦身后,本来就应该高于64MB。

第一、想象一个全新的Redis实例,启动后写入了仅仅1MB的数据。如果没有这个最小size限制,只要AOF文件大小翻倍(达到2MB,满足100%的增长),就会触发重写。重写本身是有成本(fork、I/O、CPU)的,为了节省这区区1MB的空间而进行重写是得不偿失的。64MB这个值意味着Redis认为,只有当你的数据量已经达到一定规模(至少64MB)时,重写带来的收益才值得付出这个成本。

第二、64MB是Redis社区经过长期实践得出的一个经验值,它对绝大多数开发测试环境和小型生产环境都是一个安全且合理的起点。它确保了一个非常小的Redis实例不会自己折腾自己。

第三、“万一压缩后的本来就是高于64会怎么办?”这个问题其实是一个误解。触发判断依据的是当前旧AOF文件的大小,而不是重写后新AOF文件的大小“压缩后高于64MB”是正常且普遍的情况64MB只是一个触发重写的下限门槛,而不是重写后文件大小的上限。只要你的数据集本身大于64MB,重写后的文件也必然大于64MB。

第四、压缩后的长时间高于64MB,这样就会不停地触发重写,重写本身是有成本(fork、I/O、CPU)的。折旧这就说明你该调参了。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 200MB

第五、如果AOF追加磁盘满了,会怎么样?Redis主进程在尝试执行write系统调用,向AOF文件追加命令时,操作系统会返回一个错误(如ENOSPC),告知磁盘空间已满。

(3)AOF与RDB的混合持久化(4.x后的新特性)

  • yes:AOF重写,redis会把当前所有的数据以rdb形式存入到aof中,这都是二进制数据,数据量小,随后新的数据以aof形式追加到这个aof中,那么这个aof中包含两种文件类型数据,一个是rdb,一个是aof,那么恢复的时候redis会同时恢复,这样恢复过程会更快。这相当于是一个混合体。
  • no:关闭混合模式,aof只会压缩重复的命令,这是4.x以前老版本的机制,也就是把重复的没有意义的指令去除,减少文件体积,也减少恢复的时间。

在重写AOF的时候,如果有新的命令进来要写入怎么办?那么他其实也会fork一个子进程,子进程复制重写,而新的那些写入命令会被记录到一个缓冲区,待子进程重写完毕后,缓冲工区的新的写命令会被追加到新的AOF文件中,这样就保持了数据在重写前后的一致性。

(3).修复损坏AOF文件

上面也讲了损坏情况

redis-check-aof --fix [aof文件名]
目的:删除不符合语法的指令

aof-load-truncated yes:Redis启动加载aof,命令语法不完整则修复。设置为no,Redis启动失败,需要手动用redis-check-aof 工具修复

(4)生产环境推荐策略

通常,为了在性能和安全性之间取得最佳平衡,建议同时开启 RDB 和 AOF

  1. 使用 RDB:定期做冷备,用于快速恢复和历史归档。

  2. 使用 AOF:使用 appendfsync everysec 策略,保证最多只丢失一秒的数据。

这样,在 Redis 重启时:

  • 如果 AOF 文件存在,优先加载 AOF 文件(因为它的数据更完整)。

  • 如果 AOF 文件不存在,则加载 RDB 文件。

如果说用户对redis的写操作不多甚至没有,95%以上都是读操作,那么用rdb也没啥问题。我们有一个项目是采用的缓存预热方式,用户几乎没有写操作,所以直接采用RDB就够用了,因为哪怕redis挂了,甚至RDB没了,数据还是能通过预热重新载入。
如果说你们的Redis要作为一部分的数据库来使用,那么需要用到aof,或者rdb&aof的混合模式,这样数据的完整性就更大了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96544.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hexo文章

文章目录Tag的使用勾选框图片的组合站内文章引用注意&#xff1a;1、关于中括号的问题目录总结 Tag的使用 在 markdown 中加入如下的代码来使用便签&#xff1a; {% note success %} 文字 或者 markdown 均可 {% endnote %}或者使用 HTML 形式&#xff1a; <p class&quo…

技术面:Spring (bean的生命周期、创建方式、注入方式、作用域)

Spring Bean的生命周期是什么样的&#xff1f; 在Spring容器里一个Bean的从创建到销毁一般都是经历了以下几个阶段&#xff1a; 定义阶段&#xff08;Bean元信息配置&#xff09;>实例化阶段&#xff08;创建Bean对象&#xff09;>初始化阶段&#xff08;执行初始化逻辑&…

SpringSecurity的应用

官方文档 一、核心能力 1.1 身份认证 (Authentication) - “你是谁&#xff1f;” 多种认证方式&#xff1a;支持几乎所有主流认证方案&#xff0c;如表单登录&#xff08;Username/Password&#xff09;、HTTP Basic、HTTP Digest、OAuth 2.0、OIDC (OpenID Connect)、SAML …

跨境云手机与传统手机的不同之处

传统手机主要满足个人日常生活中的通讯、娱乐、办公等基础需求&#xff0c;比如用于日常打电话联系亲朋好友&#xff0c;闲暇时刷短视频、玩本地安装的游戏&#xff0c;或者简单处理一些文档、邮件等办公事务。跨境云手机主要是侧重于跨境业务场景&#xff0c;对于从事跨境电商…

MemGPT: Towards LLMs as Operating Systems

1 MemGPT: Towards LLMs as Operating Systems 论文地址&#xff1a;MemGPT: Towards LLMs as Operating Systems 代码地址&#xff1a;https://github.com/letta-ai/letta 1.1 MemGPT MemGPT&#xff08;MemoryGPT&#xff09;借鉴传统操作系统的分层内存管理思想&#xff08;…

MICAPS:气象信息综合分析与处理系统概述

1.概述 说明:Meteorological Information Comprehensive Analysis and Process System 中文意思:气象信息综合分析处理系统。它是中国气象局开发的一套气象数据分析、处理和可视化系统,用于气象资料的收集、整理、分析和发布。 2.MICAPS 的用途 说明: 数据收集:接收来自…

MySQL-day2_02

MySQL-day2&#xff08;四&#xff09;排序&#xff08;五&#xff09;聚合函数一、count 总记录数二、max 最大值三、min 最小值四、sum 求和五、avg 平均值&#xff08;六&#xff09;数据分组一、分组二、分组后的数据筛选&#xff08;七&#xff09;数据分页显示一、获取部…

HarmonyOS应用开发:深入ArkUI声明式开发范式与最佳实践

HarmonyOS应用开发&#xff1a;深入ArkUI声明式开发范式与最佳实践 引言 随着HarmonyOS 4.0的发布及API 12的推出&#xff0c;华为的分布式操作系统进入了全新的发展阶段。ArkUI作为HarmonyOS应用开发的核心框架&#xff0c;其声明式开发范式&#xff08;Declarative Paradigm&…

Claude-Flow AI协同开发:钩子系统与 GitHub 集成

5.1 思维认知框架&#xff1a;从“开发助手”到“DevOps 智能体” 在此之前&#xff0c;我们将 Claude-Flow 视为一个强大的 “开发助手 (Development Assistant)” &#xff0c;它在编码、测试、重构等环节为我们提供支持。现在&#xff0c;我们需要再次进行思维升级&#xff…

DigitalOcean Kubernetes 现已支持 Gateway API 托管服务

在 DigitalOcean Kubernetes 集群中管理流量&#xff0c;一直以来主要依赖 Ingress。虽然能满足基本需求&#xff0c;但在灵活性、角色分离和高级路由方面仍存在局限。今天&#xff0c;我们很高兴迎来新的改变。 我们正式宣布&#xff0c;Kubernetes Gateway API 托管服务现已…

聚铭网络入选数世咨询《中国数字安全价值图谱》“日志审计”推荐企业

近日&#xff0c;国内知名数字安全咨询机构数世咨询正式发布《中国数字安全价值图谱》。聚铭网络凭借领先的技术实力与出色的市场表现&#xff0c;成功入选“日志审计”领域重点推荐企业&#xff0c;彰显了在该赛道的专业认可与品牌影响力。关于《中国数字安全价值图谱》 在当下…

豆包、Kimi、通义千问、DeepSeek、Gamma、墨刀 AI”六款主流大模型(或 AI 平台)生成 PPT 的完整流程

、先厘清 3 个概念&#xff0c;少走弯路大模型 ≠ PPT 软件豆包、Kimi、通义千问、DeepSeek 本身只负责“出大纲/出文案”&#xff0c;真正的“一键配图排版”要靠官方 PPT 助手或第三方平台&#xff08;博思 AiPPT、迅捷 AiPPT、Gamma、墨刀 AI 等&#xff09;。两条主流技术路…

Redis哈希(Hash):适合存储对象的数据结构,优势与坑点解析

Redis哈希&#xff08;Hash&#xff09;&#xff1a;适合存储对象的数据结构&#xff0c;优势与坑点解析 1. Redis哈希概述 1.1 什么是Redis哈希 Redis哈希&#xff08;Hash&#xff09;是一种映射类型&#xff08;Map&#xff09;&#xff0c;由多个字段值对&#xff08;fi…

Python的uv包管理工具使用

一、简介 uv是一个继Python版本管理、Python包管理、项目管理、虚拟环境管理于一体的工具&#xff0c;由于底层是用Rust编写的&#xff0c;uv的执行速度非常快。 安装 pip install uv镜像源设置 uv默认安装包是从pypi上下载的&#xff0c;速度比较慢。我们可以设置镜像源&#…

JavaScript事件机制与性能优化:防抖 / 节流 / 事件委托 / Passive Event Listeners 全解析

目标&#xff1a;把“为什么慢、卡顿从哪来、该怎么写”一次说清。本文先讲事件传播与主线程瓶颈&#xff0c;再给出四件法宝&#xff08;防抖、节流、事件委托、被动监听&#xff09;&#xff0c;最后用一套可复制的工具函数 清单收尾。1&#xff09;先理解“为什么会卡”&am…

【Chrome】chrome 调试工具的network选项卡,如何同时过滤出doc js css

通过类型按钮快速筛选&#xff08;更直观&#xff09;在 Network 选项卡中&#xff0c;找到顶部的 资源类型按钮栏&#xff08;通常在过滤器搜索框下方&#xff09;。按住 Ctrl 键&#xff08;Windows/Linux&#xff09;或 Command 键&#xff08;Mac&#xff09;&#xff0c;同…

Elasticsearch (ES)相关

在ES中&#xff0c;已经有Term Index&#xff0c;那还会走倒排索引吗 你这个问题问得很到位 &#x1f44d;。我们分清楚 Term Index 和 倒排索引 在 Elasticsearch (ES) 里的关系&#xff1a;1. 倒排索引&#xff08;Inverted Index&#xff09; 是 Lucene/ES 检索的核心。文档…

pre-commit run --all-files 报错:http.client.RemoteDisconnected

报错完整信息初步原因是这样 报错是 Python 的 http.client.RemoteDisconnected&#xff0c;意思是 在用 urllib 请求远程 URL 时&#xff0c;远程服务器直接断开了连接&#xff0c;没有返回任何响应。在你的堆栈里&#xff0c;它出现在 pre-commit 尝试安装 Golang 环境的时候…

【C++】STL·List

1. list的介绍及使用 1.1list介绍 List文档介绍 1.2 list的使用 list中的接口比较多&#xff0c;此处类似&#xff0c;只需要掌握如何正确的使用&#xff0c;然后再去深入研究背后的原理&#xff0c;已 达到可扩展的能力。以下为list中一些常见的重要接口。 1.2.1 list的构造…

图论2 图的数据结构表示

目录 一 图的数据结构表示 1 邻接矩阵&#xff08;Adjacency Matrix&#xff09; 2 邻接表&#xff08;Adjacency List&#xff09; 3 边列表&#xff08;Edge List&#xff09; 4 十字链表&#xff08;Orthogonal List / Cross-linked List, 十字链表&#xff09; 5 邻接…