Redis基础总结、持久化、主从复制、哨兵模式、内存淘汰策略、缓存
文章目录
- Redis 基础
- Redis 是什么,有哪些特点
- 为什么要使用 Redis 而不仅仅依赖 MySQL
- Redis 是单线程吗
- Redis 单线程为什么还这么快
- Redis 数据类型和数据结构
- 五种基本数据结构及应用场景
- 其他数据类型
- Redis 底层数据结构
- Redis 持久化
- 数据不丢失的实现
- AOF 日志
- RDB 快照
- 混合持久化
- AOF 和 RDB 的选择
- AOF 重写的执行过程
- RDB 快照的执行过程
- 混合持久化的执行过程
- Redis 功能和高可用性
- 主从复制
- 全量复制
- 增量复制
- 全量复制使用 RDB 的原因
- 哨兵模式
- 切片集群
- 集群脑裂
- 过期删除
- 内存淘汰策略
- LRU 和 LFU 算法
- Redis缓存
- 缓存雪崩
- 应对策略
- 缓存击穿
- 缓存穿透
- 常见原因及处理方法
- 保证数据库和缓存的一致性
- 写策略
- 读策略
- 保证删除缓存操作一定能成功
- 重试机制
- 订阅BINLog
Redis 基础
Redis 是什么,有哪些特点
Redis 是一个开源的基于内存的数据库,具有以下特点:
- 基于内存:读写速度非常快,适用于缓存、高性能应用场景。
- 持久性:支持将数据持久化到磁盘,防止数据丢失。
- 多数据结构:支持字符串、哈希表、列表、集合、有序集合等。
- 原子性操作:保证操作的原子性,确保数据一致性。
- 分布式特性:提供多种集群方案,提高可扩展性和可用性。
为什么要使用 Redis 而不仅仅依赖 MySQL
- 高性能:读写速度快,适用于频繁读写的数据。
- 高并发:高效处理并发请求,适用于快速响应的场景。
- 丰富的数据结构:处理特定类型数据和实现特定功能更灵活。
- 减轻数据库压力:缓存常用数据,减轻 MySQL 等数据库的压力。
Redis 是单线程吗
Redis 的网络请求模块是单线程的,但其他模块使用多线程,以提高性能。
Redis 单线程为什么还这么快
- 基于内存存储:内存访问速度快。
- 非阻塞单线程:避免多线程竞争和同步开销。
- 高效的数据结构:如 STRING、LIST、HASH 等。
- I/O 多路复用:同时监听多个 Socket,实现高效并发处理。
Redis 数据类型和数据结构
五种基本数据结构及应用场景
- String(字符串):缓存对象、计数、分布式锁。底层的数据结构实现主要是SDS(简单动态字符串)
- List(列表):消息队列。底层数据结构是双向链表或者压缩列表
- Set(集合):点赞、共同关注、抽奖活动。底层由哈希表或整数集合(都是整数且元素个数小于 512个)实现
- Hash(哈希):缓存对象、购物车。底层由哈希表或压缩列表(哈希类型元素个数小于512个,所有值小于 64 字节)实现
- Zset(有序集合):排行榜。底层数据结构压缩列表或跳表

其他数据类型
- BitMap:签到统计、用户登陆态判断。
- HyperLogLog:基数统计,如网页面 UV 计数。不准确。优点在输入元素的 数量或者体积非常非常大时,所需的内存空间总是固定的、并且很小
- GEO:存储地理位置信息。
- Stream:消息队列。自动生成全局唯一ID,支持以消费组形式消费数据
Redis 底层数据结构
- SDS(简单动态字符串):动态扩容,支持字符串和二进制数据。
- 双端链表:快速插入和删除。无法很好的利用CPU缓存,内存开销比较大
- 压缩列表:压缩列表是一种紧凑的、可变⻓度,由连续内存块组成的顺序型数据结构。在内存使用效率上比较高
- 哈希表:快速查询,采用了拉链法解决哈希冲突。
- 整数集合:高效存储整数值。二进制表示
- 跳表:多层有序链表,查找复杂度 O(logN)。
- quicklist:双向链表+压缩列表的组合。quicklist 就是一个链表,而链表中的每个元素又是一个压缩列 表
- listpack:只记录当前节点的长度,避免连锁更新问题。

Redis 持久化
数据不丢失的实现
Redis 通过以下三种方式实现数据持久化,将数据存储到磁盘,确保在重启时可以恢复数据:
- AOF 日志:记录每个写操作命令,以日志形式存储。
- RDB 快照:定期将内存数据快照保存为二进制文件。
- 混合持久化:结合 AOF 和 RDB 的优点,提供更快的恢复速度和较少的数据丢失。
AOF 日志
- 机制:先执行命令,把数据写入内存,记录每个写操作命令,重启时重放日志恢复数据。
- 优点:避免记录错误命令,不阻塞当前写操作。
- 写回策略:
- Always:每次写操作后立即写回磁盘,最安全,但性能较低。
- Everysec:每秒写回一次,折中方案,性能和数据安全性较好。
- No:由操作系统控制写回时机,性能最高,但数据安全性较低。
- 重写机制:扫描数据中所有的键值对数据,然后为每一个键值对生成一条写操作命令,接着将该命令写入到新的 AOF 文件,重写完成后,就替换掉现有的 AOF 日志。重写的过程是由后台子进程完成的,这样可以使得主进程可以继续正常处理命令。
- 触发时机:
- 手动执行
bgrewriteaof命令。 - 主从复制完成。
- AOF 重写被设置为待调度执行。
- AOF 文件大小比例超出阈值,以及 AOF 文件的大小绝对值超出阈值。
- 手动执行
- 触发时机:
RDB 快照
- 机制:记录某一时刻的内存数据快照,以二进制方式保存到磁盘。
- 优点:数据恢复速度快,文件体积小。
- 缺点:频率太低会丢失数据,频率太高会影响性能。
- 生成方式:
- save:在主线程执行,可能阻塞 Redis 的其他操作。
- bgsave:在子进程执行,避免阻塞主线程,适合大规模数据保存。
混合持久化
- 机制:结合 AOF 和 RDB,先将内存数据以 RDB 方式写入 AOF 文件,然后将增量命令以 AOF 方式写入。文件前半部分是 RDB 格式的全量数据(加载速度快),后半部分是 AOF 格式的增量数据(数据丢失更少)。
- 优点:快速恢复数据,降低数据丢失风险,结合了 RDB 的快速加载和 AOF 的持久性优势。
- 缺点:AOF 文件可读性变差,兼容性较差(Redis 4.0 之前版本不支持)。
AOF 和 RDB 的选择
- AOF 优点:持久性更好,丢失数据较少,但恢复速度较慢。
- RDB 优点:数据恢复速度快,但快照频率难以掌控。
- 混合持久化:综合两者优点,适合需要快速恢复数据且不希望数据丢失的场景。
AOF 重写的执行过程
- 启动重写:手动或触发条件满足时,Redis 启动 AOF 重写。
- 生成新文件:子进程遍历所有数据,生成新的 AOF 文件。
- 处理增量数据:在生成新文件过程中,增量数据被记录到缓冲区。
- 替换旧文件:新 AOF 文件生成完毕后,增量数据写入新文件,替换旧 AOF 文件。
RDB 快照的执行过程
- save 命令:主线程执行,阻塞其他操作。
- bgsave 命令:子进程执行,避免主线程阻塞。
- 文件生成:快照生成的文件包含当前内存中的所有数据。
- 文件加载:重启时加载 RDB 文件恢复数据。
混合持久化的执行过程
- 启动重写:AOF 重写过程中,子进程将内存数据以 RDB 方式写入 AOF 文件。
- 记录增量数据:主线程处理的操作命令记录到重写缓冲区,以 AOF 方式写入新文件。
- 文件替换:新文件生成后,通知主进程将其替换旧文件。新文件前半部分为 RDB 格式数据,后半部分为 AOF 格式数据。
- 快速恢复:重启时,先加载 RDB 部分,快速恢复大部分数据,再加载 AOF 部分,确保数据一致性。
Redis 功能和高可用性
主从复制

Redis 通过主从复制模式实现数据的高可用性,保证数据副本的一致性。主从复制模式下,读写操作分离:
- 读操作:主库和从库都可以接收。
- 写操作:先在主库执行,然后同步到从库。
全量复制
- 建立连接:从库与主库建立连接,主库确认后开始同步。
- 主库发送数据:主库发送当前数据的 RDB 快照及增量写命令。
- 从库接收数据:从库接收 RDB 文件和增量写命令,更新数据状态。

增量复制
从库发生宕机,重新连接后数据的同步操作(增量复制)

- 从库宕机重连:从库发生宕机,主库会把断连期间收到的写操作命令,写到repl_backlog_buffer中;从库重新连接主库后,发送 psync 命令并传递当前的复制偏移量slave_repl_offset。
- 数据同步:主库根据从库的复制偏移量,决定进行增量复制还是全量复制(从库相差 > repl_backlog_buffer)。
全量复制使用 RDB 的原因
- 压缩数据:RDB 文件内容是经过压缩的二进制,文件较小。
- 性能影响小:AOF 文件需要选择文件刷盘的策略,选择不当会影响性能,而 RDB 文件只在备份和同步时生成。
哨兵模式
Redis 的哨兵模式用于监控主从服务器,提供主从节点故障转移的功能,实现自动故障转移和高可用性。哨兵的功能包括:
- 监控:定期检查主从服务器状态。
- 通知:发现问题时通知相关人员。
- 故障迁移:自动主从切换。
- 配置管理:统一管理主从地址。
切片集群
当缓存数据量大到一台服务器无法承载时,使用 Redis 切片集群将数据分布在多个服务器上,降低系统对单主机点的依赖,提高读写性能。切片集群的工作原理:
- 数据分片:将数据集划分为 16384 个槽,每个节点管理部分槽的数据。
- 节点间通信:节点通过 gossip 协议互相通信,保持一致性。
- 数据分布:根据键的 CRC16 哈希值确定数据属于哪个槽,并存储到相应节点。
- 故障检测:哨兵机制检测节点状态,重新分配槽并选举新主节点。
- 客户端路由:客户端根据键的哈希值确定目标节点,直接与负责数据的节点通信。
- 数据复制:每个槽有一个主节点和若干个从节点,数据写入主节点后异步复制到从节点。
集群脑裂
脑裂是指在网络故障时,主节点的网络突然发生了问题与所有的从节点都失联,但与客户端正常通信,这些数据被主节点缓存到了缓冲区里。哨兵 也发现主节点失联了,就会在从节点中选举出一个leader作为主节点,导致出现多个主节点。解决方法:
- 主节点写保护:主节点在发现从节点断开或通信超时数量少于阈值时,禁止写操作。
- 从节点配置:设置主节点需要从节点的 ACK 消息数量和延迟限制,确保数据一致性。
过期删除
Redis 支持为键设置过期时间,自动删除过期键值对,采用以下删除策略:
- 定时删除:设置定时事件,到时间自动删除键,占用 CPU 时间多。
- 惰性删除:不主动删除,访问键时检查其是否过期,节省 CPU 时间,但可能浪费内存。
- 定期删除:每隔一段时间随机抽取部分键进行检查和删除,均衡 CPU 和内存使用。
Redis 选择「惰性删除+定期删除」这两种策略配和使用,以求在合理使用 CPU 时间和避免内存浪费之间取得平衡
内存淘汰策略
当内存不足时,Redis 会根据配置的淘汰策略删除一些键以释放内存。常见策略:
- NoEviction:不进行数据淘汰,内存不足时返回错误。
- VolatileTTL:优先淘汰更早过期的键。
- VolatileLRU:对带过期时间的键使用 LRU 策略,其他键使用 NoEviction 策略。
- VolatileRandom:对带过期时间的键随机淘汰,其他键使用 NoEviction 策略。
- VolatileLFU:对带过期时间的键使用 LFU 策略,其他键使用 NoEviction 策略。
- AllKeysLRU:根据最近最少使用原则淘汰最久未使用的键。
- AllKeysRandom:随机选择一个键进行淘汰。
- AllKeysLFU:根据最少频繁使用原则淘汰最少使用的键。
可以使用config get maxmemory-policy命令,来查看当前 Redis 的内存淘汰策略
LRU 和 LFU 算法
- LRU(Least Recently Used):淘汰最近最少使用的对象。
- 实现:随机取若干值,淘汰最久未使用的对象。
- LFU(Least Frequently Used):淘汰使用频率最低的对象。
- 实现:维护使用计数,淘汰使用计数最低的对象。
区别:
- LRU:关注最近访问情况,认为最近访问的对象更可能被再次访问。
- LFU:关注使用频率,认为使用频率低的对象未来访问概率低。
Redis缓存
由于用户请求频繁访问数据库,直接访问数据库可能导致数据库崩溃,因此常常使用Redis作为数据库的缓存层。
缓存雪崩
缓存雪崩:某个时间点,缓存中的大量数据同时失效,大量请求涌向数据库,导致数据库压力剧增。原因可能是缓存过期时间设置相近或Redis故障。
应对策略
-
大量数据同时过期
- 均匀设置过期时间:加随机数,避免大量数据同一时间失效。
- 使用互斥锁:确保同一时间只有一个请求构建缓存。
- 后台线程定时更新缓存:让缓存设置“永久有效”。
-
Redis故障宕机
- 服务熔断或请求限流:减少直接对数据库的压力。
- 构建Redis高可靠集群:通过主从节点切换确保服务连续。
缓存击穿
缓存击穿:热点数据过期时,大量并发请求查询该数据,导致直接访问数据库,增加数据库负载。可以通过互斥锁或后台更新缓存来解决。
缓存穿透
缓存穿透:请求的数据既不在缓存中,也不在数据库中,导致所有请求直接访问数据库,增加负载。
常见原因及处理方法
- 业务误操作或恶意攻击。
- 对非法请求做限制。
- 缓存中设置空值或默认值。
- 使用布隆过滤器判断数据是否存在。

保证数据库和缓存的一致性
Cache Aside策略:
写策略
- 更新数据库后删除缓存。
读策略
- 缓存命中返回数据;未命中从数据库读取数据后写入缓存并返回。
为了高缓存命中率,可以采用更新数据库加更新缓存的方法,但需解决并发导致的一致性问题,例如加分布式锁或设置较短的缓存过期时间。
保证删除缓存操作一定能成功
重试机制
引入消息队列,应用删除失败从消息队列重新读取数据再进行删除,重试多次未成功则报错。
订阅BINLog
订阅binlog日志,准确删除缓存中的数据。通过模拟MySQL从节点获取binlog,解析后删除缓存数据。
相关文章:
Redis基础总结、持久化、主从复制、哨兵模式、内存淘汰策略、缓存
文章目录 Redis 基础Redis 是什么,有哪些特点为什么要使用 Redis 而不仅仅依赖 MySQLRedis 是单线程吗Redis 单线程为什么还这么快 Redis 数据类型和数据结构五种基本数据结构及应用场景其他数据类型Redis 底层数据结构 Redis 持久化数据不丢失的实现AOF 日志RDB 快…...
Java与Python优劣势对比:具体例子与深入分析
在软件开发的世界里,Java和Python是两座不可忽视的高峰。它们各自拥有独特的优势和应用场景,为开发者提供了多样化的选择。本文将通过具体例子,深入分析Java和Python在不同方面的表现,以期为读者提供更为详尽的参考。 1. 语法简洁…...
C++内存泄漏介绍
C内存泄漏(Memory Leak)是指程序在运行过程中,动态分配的内存没有被适当地释放或回收,导致这部分内存始终被占用,无法再被程序或其他程序使用。这种情况通常发生在使用了new或malloc等函数动态分配内存后,忘…...
C++分析红黑树
目录 红黑树介绍 红黑树的性质与平衡控制关系 红黑树节点的插入 情况1:不需要调整 情况2:uncle节点为红色 情况3:uncle节点为黑色 总结与代码实现 红黑树的删除(待实现) 红黑树的效率 红黑树介绍 红黑树是第二种平衡二…...
mysql线上查询之前要性能调优
查询优化是数据库性能调优的关键方面,目的是减少查询的执行时间和资源消耗。以下是一些常见的查询优化技巧及其示例: 使用合适的索引 问题: 全表扫描导致查询缓慢优化: 为经常用于搜索条件的列添加索引示例: 假设有一…...
GPIO输出控制之LED闪烁、LED流水灯以及蜂鸣器应用案例
系列文章目录 STM32之GPIO(General Purpose Input/Output,通用型输入输出) 文章目录 系列文章目录前言一、LED和蜂鸣器简介1.1 LED1.2 蜂鸣器1.3 面包板 二、LED硬件电路2.1 低电平驱动电路2.2 高电平驱动电路 三、蜂鸣器硬件电路3.1 PNP型三…...
体系结构论文导读(三十四):Design of Reliable DNN Accelerator with Un-reliable ReRAM
文章核心 这篇文章主要讨论了一种在不可靠的ReRAM(阻变存储器)设备上设计可靠的深度神经网络(DNN)加速器的方法。文章提出了两种关键技术来解决ReRAM固有的不可靠性问题:动态定点(DFP)数据表示…...
WebStock会话
其实使用消息队列也可以实现会话,直接前端监听指定的队列,使用rabbitmq的分组还可以实现不同群聊的效果。 1、依赖搭建: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org…...
5_现有网络模型的使用
教程:现有网络模型的使用及修改_哔哩哔哩_bilibili 官方网址:https://pytorch.org/vision/stable/models.html#classification 初识网络模型 pytorch为我们提供了许多已经构造好的网络模型,我们只要将它们加载进来,就可以直接使…...
软件安全测试报告内容和作用简析,软件测试服务供应商推荐
在数字化时代,软件安全问题愈发凸显,安全测试显得尤为重要。软件安全测试报告是对软件系统在安全性方面进行评估和分析后的书面文件。该报告通常包含测试过程、测试发现、漏洞描述、风险评估及改进建议等重要信息。报告的目的是为了帮助开发团队及时发现…...
算法板子:树形DP、树的DFS——树的重心
思想: 代码: #include <iostream> #include <cstring> using namespace std;const int N 1e5 10;// vis标记当前节点是否被访问过; vis[1]true代表编号为1的节点被访问过 bool vis[N]; // h数组为邻接表; h数组上的每个坑位都串了一个单链…...
在C语言中,联合体或共用体(union )是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。
在C语言中,union 是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。这意味着 union 中的所有成员共享同一块内存空间,因此它们之间会相互覆盖。在你给出的 Acceleration_type union 定义中,包含了三种不同类型的成员…...
MS2201以太网收发电路
MS2201 是吉比特以太网收发器电路,可以实现超高速度的 全双工数据传输。它的通信遵从 IEEE 802.3 Gigabit Ethernet 协议 中的 10 比特接口的时序要求协议。 MS2201 支持数据传输速率从 1Gbps 到 1.85Gbps 。 主要特点 ◼ 电源电压: 2.5V 、 3.3V …...
乐乐音乐Kotlin版
简介 乐乐音乐Kotlin版,主要是基于ExoPlayer框架开发的Android音乐播放器,它支持lrc歌词和动感歌词(ksc歌词、krc歌词、trc歌词、zrce歌词和hrc歌词等)、多种格式歌词转换器及制作动感歌词、翻译歌词和音译歌词。 编译环境 Android Studio Jellyfish | …...
C语言——预处理和指针
C语言——预处理和指针 预处理宏宏定义宏的作用域带参的宏 文件包含条件编译 指针指针的概念指针的定义指针变量初始化指针一维整型数组 预处理 编程的流程分为:编辑、编译、运行、调试四个阶段; 预处理属于编译阶段,编译过程又可以分为&…...
iptables防火墙(一)
目录 1、Linux防火墙基础 2、iptables的四表五链结构 2.1 iptables的四表五链结构介绍 2.2 四表五链 2.2.1 四表 2.2.2 五链 2.3 包过滤的匹配流程 2.3.1 规则链之间匹配顺序 2.3.2 规则链内部的处理规则 2.3.3 数据包过滤的匹配流程 3、 编写防火墙规则 3.1 iptabe…...
(leetcode学习)50. Pow(x, n)
实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。 示例 1: 输入:x 2.00000, n 10 输出:1024.00000示例 2: 输入:x 2.10000, n 3 输出:9.26100示例 …...
QT 5.12.0 for Windows 安装包 QT静态库 采用源码静态编译生成
qt-5.12.0-static.zip 下载地址(资源整理不易,下载使用需付费,且文件较大,不能接受请勿浪费时间下载): 链接:https://pan.baidu.com/s/1ftfHFG_jGFwVaOAvBVrNFg?pwdtvtp 提取码:tvtp...
【生成式人工智能-三-promote 神奇咒语RL增强式学习RAG】
如何激发模型的能力 提示词 promotCoTRL 增强式学习Reforcement learning提供更多的资料提供一些范例Incontext- learning 任务拆解让模型自己检查错误让模型多次生成答案Tree of Thoughts让模型使用其他工具RAG写程序POT其他工具 让多个模型合作参考 在模型不变的情况下&#…...
C++连接oracle数据库连接字符串
//远程连接,需要安装oracle客户端sprintf(szConnect4, ("Provider OraOLEDB.Oracle.1; Password %s; Persist Security Info True; User ID %s; Data Source \"(DESCRIPTION (ADDRESS_LIST (ADDRESS (PROTOCOL TCP)(HOST %s)(PORT 1521)) )(CONN…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
