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

redis大全

1 redis安装和简介

基于ubuntu系统的安装

sudo apt update
sudo apt install redis##包安装的redis 没有默认配置文件 

启动

redis-server /path/to/your/redis.confredis-cli

Redis 默认是没有设置用户和密码的,即可以无密码访问
设置密码的方法:可以通过修改 Redis 的配置文件redis.conf来设置密码。打开配置文件,找到requirepass这一行,将其后面的值设置为你想要的密码,例如requirepass mypassword。保存配置文件后,重启 Redis 服务使设置生效。
通过命令行设置密码:也可以在 Redis 运行时通过命令行动态设置密码。先使用CONFIG SET requirepass "mypassword"命令设置密码,然后使用CONFIG REWRITE命令将配置写入配置文件,这样即使 Redis 重启,密码设置也会保留。
验证密码:设置密码后,客户端在连接 Redis 时需要提供密码进行验证。可以在redis-cli连接时使用-a参数指定密码,如redis-cli -a mypassword。如果是在代码中连接 Redis,也需要在连接配置中设置密码。

Redis 是Remote Dictionary Service 的简称;也是远程字典服务;

数据模型

  • Redis:是 KV(键值对)数据库,支持多种数据结构,如字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)等。数据以键值对形式存储,键是唯一标识,值可以是不同的数据结构,适合存储半结构化或非结构化数据,例如缓存用户信息、商品数据等。
  • MySQL:是关系型数据库,数据以表格形式存储,由行和列组成,支持事务处理、外键约束等,适合存储结构化数据,如订单数据、用户订单详情等。

存储方式

  • Redis:数据全部存储在内存中,读写速度极快,能支持高并发。但内存空间有限,通常用于存储热点数据或临时数据。为了保证数据的可靠性,Redis 提供了持久化机制,如 RDB(快照)和 AOF(追加日志),可以将内存中的数据定期或实时地保存到磁盘上。
  • MySQL:数据主要存储在磁盘上,虽然也有内存缓存机制(如 InnoDB 缓冲池)来提高读写性能,但整体读写速度比 Redis 慢。不过,它能存储大量数据,适合长期存储和处理大规模数据。

性能特点

  • Redis:单线程模型,基于内存操作,读写速度快,能达到每秒数万甚至数十万次的并发处理能力。适用于对读写性能要求极高、数据量相对较小、对数据实时性要求高的场景。
  • MySQL:虽然性能也不错,但由于涉及磁盘 I/O 操作,在处理高并发读写时性能不如 Redis。不过,通过合理的索引设计、查询优化和数据库集群等技术,也能满足大多数企业级应用的性能需求。

Redis 6.0 及之后(网络 I/O 多线程)
多线程特性:Redis 6.0 开始支持网络 I/O 的多线程。在处理客户端的网络请求时,会使用多个线程并行处理网络读写操作,但真正的命令执行仍然是单线程的
多线程优势:网络 I/O 多线程能够显著提升 Redis 在高并发场景下的网络处理能力,充分利用多核 CPU 的优势,减少网络 I/O 的瓶颈,从而提高整体的吞吐量。
配置灵活:Redis 6.0 的多线程是可配置的,用户可以根据实际的硬件资源和业务需求来决定是否开启多线程以及使用多少个线程,具有较高的灵活性。

redis返回值

  • 简单字符串(Simple Strings)
    格式:以 + 开头,后面紧跟字符串内容,最后以 \r\n 结尾。
    含义:通常用于表示命令执行成功,返回一个简单的状态信息。
    示例:执行 SET key value 命令,若成功,Redis 会返回 +OK\r\n,表明键值对设置成功。
  • 错误信息(Errors)
    格式:以 - 开头,后面紧跟错误信息内容,最后以 \r\n 结尾。
    含义:表示命令执行过程中出现错误,错误信息会提示具体的错误类型和原因。
    示例:执行一个不存在的命令 NONEXISTENTCOMMAND,Redis 会返回 -ERR unknown command ‘NONEXISTENTCOMMAND’\r\n,指出该命令未被识别。
  • 整数(Integers)
    格式:以 : 开头,后面紧跟整数值,最后以 \r\n 结尾。
    含义:整数返回值可用于多种场景,如表示操作影响的元素数量、键的过期时间等。
    示例:
    执行 INCR key 命令,若键不存在,Redis 会先将其初始化为 0 再进行自增操作,返回 :1\r\n,表示自增后的值为 1。
    执行 EXISTS key 命令,若键存在,返回 :1\r\n;若不存在,返回 :0\r\n。
  • 批量字符串(Bulk Strings)
    格式:以 $ 开头,后面紧跟字符串的长度,然后是字符串内容,最后以 \r\n 结尾。若字符串为空,长度为 0;若键不存在,返回 $-1\r\n。
    含义:用于返回单个字符串值。
    示例:执行 GET key 命令,若键存在且值为 value,Redis 会返回 $5\r\nvalue\r\n,其中 5 是字符串 value 的长度。
  • 数组(Arrays)
    格式:以 * 开头,后面紧跟数组元素的数量,然后依次列出每个元素的返回值。
    含义:用于返回多个值,如执行 LRANGE key start stop 命令时,会返回列表中指定范围的元素数组。
    示例:执行 LRANGE mylist 0 1 命令,若列表 mylist 包含元素 element1 和 element2,Redis 会返回 *2\r\n$8\r\nelement1\r\n$8\r\nelement2\r\n,表示数组有 2 个元素,分别是 element1 和 element2。

2 数据结构

在 Redis 中,键(Key)只能是字符串类型。这是 Redis 设计的基本规则,无论值(Value)是什么数据结构(如字符串、列表、哈希、集合、有序集合等 ),键都必须是字符串。
在这里插入图片描述
redis 命令 参考

2.1 string

字符数组,该字符串是动态字符串 raw,字符串长度小于1M 时,加倍扩容;超过 1M 每次只多扩
1M;字符串最大长度为 512M;

注意:redis 字符串是二进制安全字符串;可以存储图片,二进制协议等二进制数据

基础命令

SET role:10001 '{["name"]:"mark",["sex"]:"male",["age"]:30}'

GET role:10001

批量设置值
mset key1 value1 key2 value2 ... :一次性设置多个键值对。例如 mset user:1:name "Bob" user:1:age "30" ,可同时设置两个键值对。这是原子操作,要么所有键值对都设置成功,要么都不成功 。
批量获取值
mget key1 key2 … :一次性获取多个键对应的值。例如执行 mget user:1:name user:1:age ,会返回这两个键对应的值。对于不存在的键或非字符串类型值对应的键,返回 nil 。
追加值
append key value :如果键 key 存在,将 value 追加到该键原有的值后面;若键不存在,则创建一个新键,值为 value 。例如,先执行 set city "Bei" ,再执行 append city "jing" ,此时 get city 会返回 "Beijing"

位运算

# 月签到功能 10001 用户id 202106 2021年6月份的签到 6月份的第1天
setbit sign:10001:202106 1 1
# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106
# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2

setbit :命令名称,用于设置或清除键对应字符串值中特定偏移量处的位。
key :这里是 sign:10001:202106 ,表示要操作的键 。键在 Redis 中用于唯一标识数据,通过它可定位到对应的值进行操作。
offset :此例中为 1 ,指要修改的位的偏移量(位置 )。偏移量从 0 开始计数,基于位索引而非字节索引。比如要操作第 3 个位,offset 就写 2 。
value :这里是 1 ,表示要将指定偏移量处的位设置成的值 ,只能是 0 或 1 。1 代表设置该位为 1 ,0 代表设置该位为 0 。

签到功能:像 setbit sign:10001:202106 1 1 ,可以表示用户 10001 在 2021 年 6 月第 2 天(因为 offset 从 0 开始 )签到(设定位值为 1 代表签到 )。后续可结合 bitcount 命令统计该用户当月签到天数,或用 getbit 命令获取某一天签到状态。

2.1 list

双向链表实现,列表首尾操作(删除和增加)时间复杂度 O(1) ;查找中间元素时间复杂度为O(n) ;

列表中数据是否压缩的依据:

  1. 元素长度小于 48,不压缩;
  2. 元素压缩前后长度差不超过 8,不压缩;

基础命令

redis 127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
redis 127.0.0.1:6379> RPUSH mylist "foo"
(integer) 2
redis 127.0.0.1:6379> RPUSH mylist "bar"
(integer) 3
redis 127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "foo"
3) "bar"

右推左出 实现了一个FIFO 先入先出

redis 127.0.0.1:6379> LPUSH list1 "foo"
(integer) 1
redis 127.0.0.1:6379> LPUSH list1 "bar"
(integer) 2
redis 127.0.0.1:6379> LRANGE list1 0 -1
1) "bar"
2) "foo"

实现了栈 先进后出

2.3 hash

散列表,在很多高级语言当中包含这种数据结构;c++ unordered_map 通过 key 快速索引value;

节点数量大于 512(hash-max-ziplist-entries) 或所有字符串长度大于 64(hash-max-ziplistvalue),则使用 dict 实现;
节点数量小于等于 512 且有一个字符串长度小于 64,则使用 ziplist 实现

基础命令

# 获取 key 对应 hash 中的 field 对应的值
HGET key field
# 设置 key 对应 hash 中的 field 对应的值
HSET key field value
# 设置多个hash键值对
HMSET key field1 value1 field2 value2 ... fieldn valuen
# 获取多个field的值
HMGET key field1 field2 ... fieldn
# 给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
# 获取 key 对应的 hash 有多少个键值对
HLEN key
# 删除 key 对应的 hash 的键值对,该键为field
HDEL key field

综合示例

127.0.0.1:6379> HMSET user:1001 name "Alice" age 25 email "alice@example.com"
OK
127.0.0.1:6379> HGET user:1001 name
"Alice"
127.0.0.1:6379> HMGET user:1001 name age
1) "Alice"
2) "25"
127.0.0.1:6379> HINCRBY user:1001 age 1
(integer) 26
127.0.0.1:6379> HGET user:1001 age
"26"
127.0.0.1:6379> HLEN user:1001
(integer) 3
127.0.0.1:6379> HDEL user:1001 email
(integer) 1
127.0.0.1:6379> HLEN user:1001
(integer) 2
127.0.0.1:6379> HGET user:1001 email
(nil)

2.4 set

集合;用来存储唯一性字段,不要求有序;

命令

SADD key member [member ...]
# 计算集合元素个数
SCARD key
# SMEMBERS key
SMEMBERS key
# 返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member
# 随机返回key集合中的一个或者多个元素,不删除这些元素
SRANDMEMBER key [count]
# 从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]
# 返回一个集合与给定集合的差集的元素
SDIFF key [key ...]
# 返回指定所有的集合的成员的交集
SINTER key [key ...]
# 返回给定的多个集合的并集中的所有成员
SUNION key [key ...]

综合示例

127.0.0.1:6379> SADD set1 apple banana cherry
(integer) 3
127.0.0.1:6379> SADD set2 banana date elderberry
(integer) 3
127.0.0.1:6379> SCARD set1
(integer) 3
127.0.0.1:6379> SISMEMBER set1 apple
(integer) 1
127.0.0.1:6379> SRANDMEMBER set1
"apple"
127.0.0.1:6379> SDIFF set1 set2
1) "apple"
2) "cherry"
127.0.0.1:6379> SINTER set1 set2
1) "banana"
127.0.0.1:6379> SUNION set1 set2
1) "cherry"
2) "date"
3) "banana"
4) "apple"
5) "elderberry"

2.5 zset

有序集合;用来实现排行榜;它是一个有序唯一;

节点数量大于 128或者有一个字符串长度大于64,则使用跳表(skiplist);
节点数量小于等于128(zset-max-ziplist-entries)且所有字符串长度小于等于64(zset-maxziplist-value),则使用 ziplist 存储;

基础命令

# 添加到键为key有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
# 从键为key有序集合中删除 member 的键值对
ZREM key member [member ...]
# 返回有序集key中,成员member的score值
ZSCORE key member
# 为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
# 返回key的有序集元素个数
ZCARD key
# 返回有序集key中成员member的排名
ZRANK key member
# 返回存储在有序集合key中的指定范围的元素 order by id limit 1,100
ZRANGE key start stop [WITHSCORES]
# 返回有序集key中,指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]

综合示例

127.0.0.1:6379> ZADD ranklist 100 "Alice" 200 "Bob" 150 "Charlie"
(integer) 3
127.0.0.1:6379> ZADD ranklist NX 250 "David"
(integer) 1
127.0.0.1:6379> ZINCRBY ranklist 50 "Alice"
"150"
127.0.0.1:6379> ZREVRANGE ranklist 0 -1 WITHSCORES
1) "David"
2) "250"
3) "Bob"
4) "200"
5) "Charlie"
6) "150"
7) "Alice"
8) "150"
127.0.0.1:6379> ZREVRANGE ranklist 0 -1 WITHSCORES
1) "David"
2) "250"
3) "Bob"
4) "200"
5) "Charlie"
6) "150"
7) "Alice"
8) "150"

NX:NX模式是Not eXists的缩写,代表 “仅当元素不存在时添加”。使用NX模式时,如果要添加的成员在有序集合中已经存在,那么该成员的分数不会被更新,也不会再次添加该成员

3 redis的连接

3.1 redis网络层

在这里插入图片描述

Redis 的并发

  • 原理:Redis 基于事件驱动的reactor模式。它使用一个事件循环来监听多个客户端连接的事件(如连接建立、数据到达等 )。当有多个客户端连接时,它会将这些连接产生的事件放入队列中,通过事件循环来快速切换处理不同连接的事件,实现对多个连接的数据并发处理。从概念上类似图中 “并发” 示意图,多个任务(连接请求 )看似同时进行处理 。这里说的并发,符合文字中 “活跃队列的个数大于处理器的个数”,即有多个任务队列等待处理器处理 。
  • 优势:能高效利用系统资源,在单线程模型下(Redis 单线程指处理命令逻辑是单线程 ),处理大量客户端的请求,提升系统的吞吐量和响应性能。例如在高并发的电商秒杀场景中,能同时处理众多用户的请求。

Redis 的串行

  • 原理:对于单条连接,Redis 处理数据是串行的。就像图中 “串行” 示意图,任务按顺序依次处理 。在同一条连接上,客户端发送的多个命令会按照先后顺序依次执行,前一个命令执行完,才会执行下一个命令。这是因为 Redis 为了保证数据操作的原子性和一致性,避免出现并发访问导致的数据错乱问题。
  • 好处:简化了数据处理逻辑和事务控制。比如在使用 Redis 实现分布式锁时,基于这种串行执行特性,能确保锁操作的正确性和可靠性。

3.2 Redis Pipeline

基本概念
Redis Pipeline 是客户端提供的功能,并非服务端提供 。它允许客户端将多个命令一次性打包发送到 Redis 服务端,而不用等待每个命令的响应后再发送下一个命令。服务端会按顺序依次处理这些命令,然后将所有结果一次性返回给客户端。
原理及优势

  • 原理:客户端执行请求操作时,只是把数据写入到对应的写缓冲区,这个过程很快。真正耗时的是读取响应阶段。通过 Pipeline,能减少客户端与服务端之间的网络往返次数(如图片中对比常规单次请求 - 响应模式 )。常规模式下每个命令都有一次网络往返,而 Pipeline 模式下多个命令只有一次网络往返 。
  • 优势:显著提升执行多个命令的性能和效率,尤其在需- 要执行大量命令且网络延迟较高的场景中。比如批量设置大量键值对时,使用 Pipeline 可大幅缩短操作时间。
#include <iostream>
#include <string>
#include <vector>
#include <hiredis/hiredis.h>// 执行 Redis Pipeline 命令
std::vector<std::string> executePipeline(redisContext* context, const std::vector<std::string>& commands) {std::vector<std::string> results;// 开始 Pipelinefor (const auto& command : commands) {if (redisAppendCommand(context, "%s", command.c_str()) != REDIS_OK) {std::cerr << "Failed to append command: " << command << std::endl;return results;}}// 执行 Pipeline 中的所有命令for (size_t i = 0; i < commands.size(); ++i) {redisReply* reply;if (redisGetReply(context, reinterpret_cast<void**>(&reply)) != REDIS_OK) {std::cerr << "Failed to get reply for command: " << commands[i] << std::endl;continue;}if (reply->type == REDIS_REPLY_STATUS || reply->type == REDIS_REPLY_STRING) {results.emplace_back(reply->str);} else if (reply->type == REDIS_REPLY_INTEGER) {results.emplace_back(std::to_string(reply->integer));} else {results.emplace_back("Unknown reply type");}freeReplyObject(reply);}return results;
}int main() {// 连接到 Redis 服务器redisContext* context = redisConnect("127.0.0.1", 6379);if (context == nullptr || context->err) {if (context) {std::cerr << "Error: " << context->errstr << std::endl;redisFree(context);} else {std::cerr << "Can't allocate redis context" << std::endl;}return 1;}// 定义要执行的 Pipeline 命令std::vector<std::string> commands = {"SET key1 value1","SET key2 value2","GET key1"};// 执行 Pipelinestd::vector<std::string> results = executePipeline(context, commands);// 输出结果for (size_t i = 0; i < results.size(); ++i) {std::cout << "Result of command " << commands[i] << ": " << results[i] << std::endl;}// 释放 Redis 上下文redisFree(context);return 0;
}

3.3 redis 的事务

Redis 事务允许将多个命令打包,然后一次性、按顺序地执行

MULTI :用于开始一个事务,调用该命令后,后续输入的所有命令不会立即执行,而是被放入一个队列,客户端会收到回复表示命令已成功入队,返回 QUEUED 。
EXEC :执行事务队列中的所有命令,并一次性将所有结果返回给客户端。即使事务中的某个命令执行失败,Redis 仍会继续执行剩余命令。
DISCARD :取消事务,会清空事务队列并退出事务状态。
WATCH key [key …] :在事务开始前监视一个或多个键。当执行 EXEC 时,若任何被监视的键被其他客户端修改,整个事务会被取消。可理解为一种乐观锁机制,避免事务执行过程中相关数据被篡改。
UNWATCH :取消对所有键的监视。

#include <iostream>
#include <string>
#include <hiredis/hiredis.h>int main() {// 连接到 Redis 服务器redisContext* context = redisConnect("127.0.0.1", 6379);if (context == nullptr || context->err) {if (context) {std::cerr << "Error: " << context->errstr << std::endl;redisFree(context);} else {std::cerr << "Can't allocate redis context" << std::endl;}return 1;}// 模拟初始账户余额redisCommand(context, "SET account:1:balance 100");redisCommand(context, "SET account:2:balance 200");while (true) {// 监视账户余额键redisCommand(context, "WATCH account:1:balance account:2:balance");redisReply* reply = static_cast<redisReply*>(redisCommand(context, "GET account:1:balance"));int balance1 = std::stoi(reply->str);freeReplyObject(reply);if (balance1 < 50) {redisCommand(context, "UNWATCH");std::cout << "余额不足,无法转账。" << std::endl;break;}// 开启事务redisCommand(context, "MULTI");// 账户 1 扣除 50redisCommand(context, "DECRBY account:1:balance 50");// 账户 2 增加 50redisCommand(context, "INCRBY account:2:balance 50");// 执行事务reply = static_cast<redisReply*>(redisCommand(context, "EXEC"));if (reply != nullptr && reply->type == REDIS_REPLY_ARRAY) {std::cout << "转账成功。" << std::endl;freeReplyObject(reply);break;}if (reply) {freeReplyObject(reply);}}// 输出转账后的余额redisReply* reply = static_cast<redisReply*>(redisCommand(context, "GET account:1:balance"));std::cout << "账户 1 余额: " << reply->str << std::endl;freeReplyObject(reply);reply = static_cast<redisReply*>(redisCommand(context, "GET account:2:balance"));std::cout << "账户 2 余额: " << reply->str << std::endl;freeReplyObject(reply);// 释放 Redis 上下文redisFree(context);return 0;
}

事务特性

  • 原子性:事务中的命令会序列化并连续执行,一般情况下要么全部执行,要么全部不执行。不过存在例外,如运行时错误(例如对字符串类型执行集合类型命令 ),此时错误命令会被忽略,其他命令仍正常执行,无法完全保证原子性。而语法错误(如命令拼写错误 )时,整个事务都不会执行,能保证原子性(全部不执行 )。
  • 隔离性:Redis 单线程执行命令,事务执行期间不会被其他客户端的命令打断,所有命令按顺序串行执行,天然保证隔离性。并且可通过 WATCH 实现乐观锁,进一步避免其他客户端修改关键数据。
  • 一致性:无论事务成功或失败,数据始终保持合法状态,如语法错误时回滚(全部不执行 )、运行时错误时保留正确操作。
  • 持久性:事务的持久性依赖持久化机制。若开启 AOF 且配置为 always 模式,事务完成后数据立即持久化;否则无法保证。

3.4 redis 发布订阅

Redis 的发布 - 订阅(Pub/Sub)是一种消息通信模式,它允许客户端之间进行消息的发送和接收,实现了消息的生产者和消费者之间的解耦

基本概念

  • 发布者(Publisher):负责生产消息并将其发送到指定的频道(Channel)。发布者不需要知道有哪些订阅者存在,只需要将消息发送到频道即可。
  • 订阅者(Subscriber):对特定的频道感兴趣,会订阅这些频道以接收发布者发送到该频道的消息。订阅者可以同时订阅多个频道,也可以动态地添加或取消订阅。
  • 频道(Channel):是消息的逻辑容器,用于区分不同类型的消息。发布者将消息发布到特定的频道,订阅者则从感兴趣的频道接收消息。

命令操作
SUBSCRIBE channel [channel …]:订阅一个或多个频道。例如,SUBSCRIBE news sports 表示订阅 news 和 sports 两个频道。
PUBLISH channel message:向指定的频道发布一条消息。例如,PUBLISH news “New article published” 表示向 news 频道发布一条消息。
UNSUBSCRIBE [channel [channel …]]:取消订阅一个或多个频道。如果不指定频道,则取消所有订阅。
PSUBSCRIBE pattern [pattern …]:订阅一个或多个符合指定模式的频道。例如,PSUBSCRIBE news.* 表示订阅所有以 news. 开头的频道。
PUNSUBSCRIBE [pattern [pattern …]]:取消订阅一个或多个符合指定模式的频道。如果不指定模式,则取消所有基于模式的订阅。

综合示例

# 客户端 1:订阅 news 和 sports 频道
SUBSCRIBE news sports# 客户端 2:订阅以 tech. 开头的所有频道
PSUBSCRIBE tech.*# 客户端 3:向 news 频道发布一条消息
PUBLISH news "Breaking news: New law passed"# 客户端 1 会收到这条消息# 客户端 3:向 tech.ai 频道发布一条消息
PUBLISH tech.ai "New AI algorithm discovered"# 客户端 2 会收到这条消息# 客户端 1:取消订阅 news 频道
UNSUBSCRIBE news# 客户端 2:取消订阅以 tech. 开头的所有频道
PUNSUBSCRIBE tech.*

4 redis的持久化

Redis 是内存数据库,数据都存储在内存中,一旦服务器进程退出或发生故障,内存中的数据就会丢失。为了解决这个问题,Redis 提供了持久化机制,将内存中的数据保存到磁盘上,以便在服务器重启后能够恢复数据。以下是 Redis 两种主要的持久化方式

4.1 RDB

RDB 持久化是将 Redis 在某个时间点上的数据集快照保存到磁盘上,生成一个二进制文件(默认名为 dump.rdb)。这个过程可以手动触发,也可以根据配置的规则自动触发。
触发方式

  • 手动触发:
    SAVE 命令:阻塞 Redis 服务器进程,直到 RDB 文件创建完毕。在阻塞期间,服务器不能处理任何客户端请求。
    BGSAVE 命令:派生出一个子进程来创建 RDB 文件,服务器进程继续处理客户端请求。子进程创建 RDB 文件完成后会向父进程发送信号,通知完成。
  • 自动触发:
    通过配置文件 redis.conf 中的 save 选项来设置自动触发的条件。例如,save 900 1 表示在 900 秒(15 分钟)内,如果至少有 1 个键被修改,则自动触发 BGSAVE 操作。

4.2 AOF(Append Only File)持久化

原理
AOF 持久化是将 Redis 执行的所有写命令追加到一个文件(默认名为 appendonly.aof)的末尾。在服务器重启时,Redis 会重新执行 AOF 文件中的命令来恢复数据。

配置选项
appendonly:是否开启 AOF 持久化,默认为 no,需要将其设置为 yes 来开启。
appendfsync:控制 AOF 文件的同步频率,有以下三个可选值:

  • always:每次执行写命令后都将 AOF 文件同步到磁盘,数据安全性最高,但性能开销最大。
  • everysec:每秒将 AOF 文件同步到磁盘一次,是一种折中方案,兼顾了数据安全性和性能。
  • no:由操作系统决定何时将 AOF 文件同步到磁盘,性能最好,但数据安全性最低。

重写机制
随着 Redis 不断执行写命令,AOF 文件会越来越大,为了避免文件过大,Redis 提供了 AOF 重写机制。AOF 重写是指将 Redis 内存中的数据以最小的命令序列重新写入到一个新的 AOF 文件中,去除冗余的命令,减小文件大小.

混合持久化(Redis 4.0 及以上)
Redis 4.0 引入了混合持久化的方式,结合了 RDB 和 AOF 的优点。在开启混合持久化后,Redis 在进行 AOF 重写时,会将当前时间点的 RDB 快照数据以二进制形式写入到新的 AOF 文件开头,然后再将重写期间产生的写命令以文本形式追加到文件末尾。这样在恢复数据时,先加载 RDB 快照部分,再执行 AOF 文件中的剩余命令,既保证了数据恢复的速度,又减少了数据丢失的风险。

5 redis的主从复制

主要用来实现 redis 数据的可靠性;防止主 redis 所在磁盘损坏,造成数据永久丢失;

主从之间采用异步复制的方式;

5.1 基础知识

全量数据同步

在这里插入图片描述

主从初次复制时,主服务器将快照文件( RDB)和缓冲的命令合并后发给从服务器,从服务器接收并加载后,完成主从数据同步。

缓冲的命令是指主服务器在执行写操作时,将这些写命令暂时存储在一个缓冲区中,以便稍后发送给从服务器

增量数据同步
全量复制后,主服务器将后续执行的写命令追加到缓冲区,从服务器定期请求缓冲区中的命令并执行,保证数据一致性。

在这里插入图片描述
服务器 RUN ID
无论主库还是从库都有自己的 RUN ID,RUN ID 启动时自动产生,RUN ID 由40个随机的十六进制字符组成;
当从库对主库初次复制时,主库将自身的 RUN ID 传送给从库,从库会将 RUN ID 保存;
当从库断线重连主库时,从库将向主库发送之前保存的 RUN ID;
从库 RUN ID 和主库 RUN ID 一致,说明从库断线前复制的就是当前的主库;主库尝试执行增量同步操作;
若不一致,说明从库断线前复制的主库并不时当前的主库,则主库将对从库执行全量同步操作

5.1 Redis 哨兵模式

哨兵模式是一种高可用性( High Availability)解决方案,旨在解决 Redis 主从复制架构中的单点故障问题。哨兵模式由多个哨兵( Sentinel)实例组成,它们共同监控主服务器( Master)和从服务器( Slave),在主服务器出现故障时自动进行故障转移( Failover),将其中一个从服务器提升为新的主服务器。

在这里插入图片描述
哨兵实例( Sentinel Instances):图中有三个哨
兵实例( sentinel1、 sentinel2、 sentinel3)。这
些哨兵实例共同监控主服务器和从服务器的状
态。
主服务器( Master Redis):负责处理写操作和
读操作,从服务器会从主服务器复制数据。
从服务器( Slave Redis):负责处理读操作,
从主服务器复制数据以保持数据一致性。
客户端( Client):与 Redis 服务器进行交互的
应用程序。

流程

sentinel 会以每秒一次的频率向所有节点(其他sentinel、主节点、以及从节点)发送 ping 消
息,然后通过接收返回判断该节点是否下线;如果在配置指定 down-after-milliseconds 时间内则被判断为主观下线

当一个 sentinel 节点将一个主节点判断为主观下线之后,为了确认这个主节点是否真的下线,它
会向其他sentinel 节点进行询问,如果收到一定数量的已下线回复,sentinel 会将主节点判定为客观下线,并通过领头 sentinel 节点对主节点执行故障转移

节点被判定为客观下线后,开始领头 sentinel 选举,需要一半以上的 sentinel 支持,选举领头sentinel后,开始执行对主节点故障转移;从从节点中选举一个从节点作为新的主节点通知其他从节点复制连接新的主节点
若故障主节点重新连接,将作为新的主节点的从节点

相关文章:

redis大全

1 redis安装和简介 基于ubuntu系统的安装 sudo apt update sudo apt install redis##包安装的redis 没有默认配置文件 启动 redis-server /path/to/your/redis.confredis-cliRedis 默认是没有设置用户和密码的&#xff0c;即可以无密码访问 设置密码的方法&#xff1a;可以通…...

C#经典算法面试题

C#经典算法面试题 递归算法 C#递归算法计算阶乘的方法 一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿卡曼引进这个表示法。 原理:亦即n!=123…(n-1)n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!n。…...

cephadm部署ceph集群

一、什么是Ceph? ceph是一个统一的、分布式的存储系统&#xff0c;设计初衷式提供较好的性能(io)、可靠性(没有单点故障)和可扩展性(未来可以理论上无限扩展集群规模)&#xff0c;这三点也是集群架构所追求的。 “统一的”:意味着Ceph可以一套存储系统同时提供对象存储、块存…...

c#OdbcDataReader的数据读取

先有如下c#示例代码&#xff1a; string strconnect "DSNcustom;UIDsa;PWD123456;" OdbcConnection odbc new OdbcConnection(strconnect); odbc.Open(); if (odbc.State ! System.Data.ConnectionState.Open) { return; } string strSql "select ID from my…...

代码随想录训练营第十八天| 150.逆波兰表达式求值 239.滑动窗口最大值 347.前k个高频元素

150.逆波兰表达式求值&#xff1a; 文档讲解&#xff1a;代码随想录|150.逆波兰表达式求值 视频讲解&#xff1a;栈的最后表演&#xff01; | LeetCode&#xff1a;150. 逆波兰表达式求值_哔哩哔哩_bilibili 状态&#xff1a;已做出 思路&#xff1a; 这道题目是让我们按照逆波…...

数据中台产品功能介绍

在数字化转型浪潮中&#xff0c;数据中台作为企业数据管理与价值挖掘的核心枢纽&#xff0c;整合分散数据资源&#xff0c;构建统一的数据管理与服务体系。本数据中台产品涵盖数据可视化、数据建设、数据治理、数据采集开发和系统管理五大平台&#xff0c;以丰富且强大的功能模…...

第四章-初始化Direct3D

首先我们需要一个错误检测和抛出机制 inline std::string ToString(const HRESULT& result) {char buffer[256];sprintf_s(buffer, "error code : 0x%08X\n", result);return std::string(buffer); }class MyException : public std::runtime_error { public:My…...

实操3:6位数码管

文章目录 文章介绍仿真图原来的仿真代码教学用开发板段选和位选对应引脚思考题实物图 文章介绍 对应“案例5_3: 6位数码管显示0或者1【静态显示】” 跳转链接 要求&#xff1a;实现开发板的6位数码管同时显示0或者1 仿真图 原来的仿真代码 #include<reg52.h> // 头文件…...

常识补充(NVIDIA NVLink技术:打破GPU通信瓶颈的革命性互联技术)

文章目录 **引言&#xff1a;为什么需要NVLink&#xff1f;**1. NVLink技术概述1.1 什么是NVLink&#xff1f;1.2 NVLink的发展历程 2. NVLink vs. PCIe&#xff1a;关键对比2.1 带宽对比2.2 延迟对比 3. NVLink的架构与工作方式3.1 点对点直连&#xff08;P2P&#xff09;3.2 …...

openwrt 使用quilt 打补丁(patch)

1,引入 本文简单解释如何在OpenWRT下通过quilt命令打补丁--patch&#xff0c;也可查看openwrt官网提供的文档 2&#xff0c;以下代码通过编译net-snmp介绍 ① 执行编译命令之后&#xff0c;进入build_dir的net-snmp-5.9.1目录下&#xff0c;改目录即为snmp最终编译的目录了 /…...

NVIDIA Halos:智能汽车革命中的全栈式安全系统

高级辅助驾驶行业正面临一个尴尬的"安全悖论"——传感器数量翻倍的同时&#xff0c;事故率曲线却迟迟不见明显下降。究其原因&#xff0c;当前行业普遍存在三大技术困局&#xff1a; 碎片化安全方案 传统方案就像"打补丁"&#xff0c;激光雷达厂商只管点云…...

k8s术语之service

Kubernetes在设计之初就充分考虑了针对容器的服务发现与负载均衡机制&#xff0c;提供了Service资源&#xff0c;并通过kube-proxy配合cloud provider 来适应不同的用于场景。随着kubernetes用户的激增&#xff0c;用户场景的不断丰富&#xff0c;又产生了一些新的负载均衡机制…...

C/C++工程中的Plugin机制设计与Python实现

C/C工程中的Plugin机制设计与Python实现 1. Plugin机制设计概述 在C/C工程中实现Plugin机制通常需要以下几个关键组件&#xff1a; Plugin接口定义&#xff1a;定义统一的接口规范动态加载机制&#xff1a;运行时加载动态库注册机制&#xff1a;Plugin向主程序注册自己通信机…...

RNN 与 CNN:深度学习中的两大经典模型技术解析

在人工智能和深度学习领域,RNN(Recurrent Neural Network,循环神经网络) 和 CNN(Convolutional Neural Network,卷积神经网络) 是两种非常重要的神经网络结构。 它们分别擅长处理不同类型的数据,在自然语言处理、计算机视觉等多个领域中发挥着关键作用。 本文将从原理…...

多模态训练与微调

1.为什么多模态模型需要大规模预训练&#xff1f; 多模态模型需要大规模预训练的原因包括&#xff1a; (1)数据丰富性&#xff1a;大规模预训练可以暴露模型于丰富的数据&#xff0c;提升其泛化能力。 (2)特征提取&#xff1a;通过预训练&#xff0c;模型能够学习到有效的特…...

【HDLBits刷题】Verilog Language——1.Basics

目录 一、题目与题解 1.Simple wire&#xff08;简单导线&#xff09; 2.Four wires&#xff08;4线&#xff09; 3.Inverter&#xff08;逆变器&#xff08;非门&#xff09;&#xff09; 4.AND gate &#xff08;与门&#xff09; 5. NOR gate &#xff08;或非门&am…...

基于深度学习的图像识别技术:从原理到应用

前言 在当今数字化时代&#xff0c;图像识别技术已经渗透到我们生活的方方面面&#xff0c;从智能手机的人脸解锁功能到自动驾驶汽车对交通标志的识别&#xff0c;再到医疗影像诊断中的病变检测&#xff0c;图像识别技术正以其强大的功能和广泛的应用前景&#xff0c;改变着我们…...

【coze】手册小助手(提示词、知识库、交互、发布)

【coze】手册小助手&#xff08;提示词、知识库、交互、发布&#xff09; 1、创建智能体2、添加提示词3、创建知识库4、测试智能体5、添加交互功能6、发布智能体 1、创建智能体 2、添加提示词 # 角色 你是帮助用户搜索手册资料的AI助手 ## 工作流程 ### 步骤一:查询知识库 1.每…...

【教学类-34-11】20250506异形拼图块(圆形、三角、正方,椭圆/半圆)的中2班幼儿偏好性测试(HTML)

背景介绍 最近在写一份工具运用报告,关于剪纸难度的。所以设计了蝴蝶描边系列和异形凹凸角拼图。 【教学类-102-20】蝴蝶三色图作品2——卡纸蝴蝶“满格变形图”(滴颜料按压对称花纹、原图切边后变形放大到A4横版最大化)-CSDN博客文章浏览阅读609次,点赞8次,收藏3次。【…...

Debian系统上PostgreSQL15版本安装调试插件及DBeaver相应配置

PostgreSQL所在Debian Linux服务器安装插件程序 在PostgreSQL数据库服务器Debian系统上执行以下命令&#xff0c;安装插件pldebugger: sudo apt install postgresql-15-pldebugger #上面这一条命令运行完好像pgsql服务自动重启了&#xff0c;看日志的样子是这样的&#xff0c…...

GD32F470+CH395Q

tcp_client配置 第一步&#xff1a;资料下载 以太网协议栈芯片 CH395 - 南京沁恒微电子股份有限公司 第二步&#xff1a;准备工程 &#xff08;1&#xff09; 首先准备一个编译无报错、可以正常打印和延时的工程文件&#xff0c;官方例程采用STM32F1芯片&#xff0c;但本文…...

解决Hyper-V无法启动Debian 12虚拟机

问题 有时&#xff0c;我们会想要在Hyper-V中运行Debian12。我们想利用该系统的ISO镜像文件安装一个全新的虚拟机。 然而&#xff0c;当我们在Hyper-V中创建了一个2代虚拟机、添加了Debian 12的网络安装&#xff08;Netinst&#xff09;ISO作为最先启动的介质时&#xff0c;Hy…...

linux redis 设置密码以及redis拓展

redis拓展:http://pecl.php.net/package/redis 在服务器上&#xff0c;这里以linux服务器为例&#xff0c;为redis配置密码。 需要永久配置密码的话就去redis.conf的配置文件中找到requirepass这个参数&#xff0c;如下配置&#xff1a; 修改redis.conf配置文件 # requirepass …...

uniapp app 端获取陀螺仪数据的实现攻略

在 uniapp 开发中&#xff0c;uni.startGyroscope在 app 端并不被支持&#xff0c;这给需要获取陀螺仪数据的开发者带来了挑战。不过&#xff0c;借助 Native.js&#xff0c;我们能调用安卓原生代码实现这一需求。接下来&#xff0c;就为大家详细介绍实现步骤&#xff0c;并附上…...

第三节:Vben Admin 最新 v5.0 对接后端登录接口(下)

文章目录 前言一、处理请求头Authorization二、/auth/user/info 接口前端接口后端接口三、/auth/codes 接口1.前端2.后端四、测试接口前言 上一节内容,实现了登录的/auth/login 接口,但是登陆没有完成,还需要完成下面两个接口。才能完成登录。 一、处理请求头Authorizatio…...

标题:基于自适应阈值与K-means聚类的图像行列排序与拼接处理

摘要&#xff1a; 本文提出了一种基于自适应阈值和K-means聚类的图像行列排序与拼接方法。通过对灰度图像的自适应二值化处理&#xff0c;计算并分析图像的左右边距&#xff0c;从而确定图像的行数与列数。通过对图像进行特征提取&#xff0c;并使用K-means聚类进行排序&#…...

修改磁盘权限为管理员

1.右击需要修改的磁盘&#xff0c;点击属性 然后一路点击确定 已经修改好了...

P1782 旅行商的背包 Solution

Description 有一个体积为 C C C 的背包和若干种物品. 前 n n n 种物品&#xff0c;第 i i i 种体积为 v i v_i vi​&#xff0c;价值 w i w_i wi​&#xff0c;有 d i d_i di​ 件. 后 m m m 种物品&#xff0c;每种对应一个函数 f ( x ) a i x 2 b i x c i f(x)a…...

Acrel-EIoT 能源物联网云平台在能耗监测系统中的创新设计

摘要 随着能源管理的重要性日益凸显&#xff0c;能耗监测系统成为实现能源高效利用的关键手段。本文详细介绍了基于安科瑞Acrel-EIoT能源物联网云平台的能耗监测系统的设计架构与应用实践。该平台采用分层分布式结构&#xff0c;涵盖感知层、网络层、平台层和应用层&#xff0…...

乘法逆元【费马小定理+扩展欧几里得】

目录 模运算性质费马小定理乘法逆元扩展欧几里得算法随机栈 模运算性质 费马小定理 a,b互质&#xff1a;gcd(a,b)1 乘法逆元 a,b互质,满足a*x同余1(mod b),x是a模b的乘法逆元&#xff0c;记作a的-1次方。 扩展欧几里得算法 求axbygcd(a,b)的一组(x,y). 随机栈 题目来源&…...

Linux进程间通信(上)(21)

文章目录 前言一、什么是进程间通信&#xff1f;概念目的本质分类 二、管道什么是管道匿名管道匿名管道的原理pipe函数匿名管道使用步骤管道读写规则管道的特点管道的四种特殊情况管道的大小 总结 前言 本篇出得有点慢&#xff0c;因为我在这里更换了我的开发环境   不再使用…...

力扣面试150题--对称二叉树

Day 41 题目描述 做法 原理&#xff1a;拆分为根节点的左右两棵子树&#xff0c;比较左子树的右和右子树的左&#xff0c;左子树的左和右子树的右 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode righ…...

深度学习系统学习系列【6】之深度学习技巧

文章目录 数据集准备数据集扩展数据预处理1. 0均值&#xff08;Zero Centralization&#xff09;代码实现 2. 归一化&#xff08;Normalization&#xff09;代码实现 3. 主成分分析&#xff08;Principal Component Analysis, PCA&#xff09;实现步骤代码实现 4. 白化&#xf…...

vue项目中渲染markdown并处理报错

前言&#xff1a;想在vue项目中渲染markdown并处理报错问题 有以下几种方式&#xff1a; 1、使用第三方Markdown插件 2、通过Markdown转HTML工具 3、使用Vue组件处理Markdown 一、首先第一种&#xff1a;使用第三方Markdown插件 安装vue-markdown插件 或者 markdown-it&#xf…...

Vue3.5 企业级管理系统实战(十七):角色管理

本篇主要探讨角色管理功能&#xff0c;其中菜单权限这里先不实现&#xff0c;后续在菜单管理中再进行实现。接口部分依然是使用 Apifox mock 的。 1 角色 api 在 src/api/role.ts 中添加角色相关 api&#xff0c;代码如下&#xff1a; //src/api/role.ts import service fro…...

【AI论文】FormalMATH:大型语言模型形式化数学推理能力基准测试

摘要&#xff1a;正式的数学推理仍然是人工智能面临的一个关键挑战&#xff0c;受到现有基准在范围和规模上的限制。 为了解决这个问题&#xff0c;我们提出了FormalMATH&#xff0c;这是一个大规模的Lean4基准&#xff0c;包含5560个经过形式验证的问题&#xff0c;这些问题涵…...

9-4 USART串口数据包

HEX数据包的接收 研究几个小问题 1.包头包尾和数据载荷重复的问题 这里定义FF为包头&#xff0c;FE为包尾&#xff0c;如果我传输的数据本身就是FF和FE怎么呢&#xff1f;那这个问题确实存在&#xff0c;如果数据和包头包尾重复&#xff0c;可能会引起误判。我们有以下几种解…...

Babylon.js学习之路《 前言:为什么要学习Babylon.js 》

文章目录 引言&#xff1a;3D 开发在 Web 中的崛起为什么需要 Web 3D 开发&#xff1f;当选火热的应用场景数据表达方式的改变 Web 3D 的独特优势跨平台与零安装开发成本低即时更新与传播便捷 WebGL 的定位与挑战WebGL 是什么&#xff1f;WebGL 的直接使用痛点 为什么需要 Baby…...

今年我国已发生三级以上地震318次

快科技5月6日消息&#xff0c;根据中国地震台网的统计&#xff0c;今年以来&#xff08;截至4月30日&#xff09;&#xff0c;我国共发生三级以上地震318次&#xff0c;其中3.0-3.9级248次&#xff0c;4.0-4.9级61次&#xff0c;5.0-5.9级7次&#xff0c;6.0-6.9级2次&#xff…...

在与大语言模型交互中的礼貌现象:技术影响、社会行为与文化意义的多维度探讨

概述 关于是否值得对 AI 保持礼貌的公众意见&#xff0c;几乎和咖啡或红酒的最新研究结果一样频繁变化——这个月被推崇备至&#xff0c;下个月又受到质疑。即便如此&#xff0c;越来越多的用户现在在提示语中加入“请”或“谢谢”&#xff0c;这不仅仅是因为习惯&#xff0c;…...

Java后端开发day42--IO流(二)--字符集字符流

&#xff08;以下内容全部来自上述课程&#xff09; 拓展. try…catch异常处理&#xff08;能看懂&#xff09; 接口&#xff1a;AutoCloseable 特点&#xff1a;特定的情况下&#xff0c;可以自动释放资源 注意&#xff1a;只有实现了AutoCloseable接口的类&#xff0c;才能…...

【HarmonyOS 5】鸿蒙发展历程

【HarmonyOS 5】鸿蒙发展历程 一、鸿蒙 HarmonyOS 版本年代记 鸿蒙 1.0&#xff1a; 2019 年 8 月 9 日&#xff0c;华为在开发者大会上正式发布鸿蒙 1.0 系统&#xff0c;这一版本首次应用于华为荣耀智慧屏产品中&#xff0c;标志着华为正式进军操作系统领域。该版本初步展现…...

使用蚁群算法求解VRPTW问题

这里写目录标题 蚁群优化算法Python实现ACO求解VRPTW问题Java实现ACO求解VRPTW问题蚁群优化算法 蚁群算法(ACO)适合求解带时间窗的车辆路径优化问题(VRPTW),主要基于其仿生智能机制与问题特性的深度契合,具体体现在以下六个方面: 时间窗约束的自然映射 信息素导向与时间…...

内存的位运算

示例&#xff1a;提取和设置标志位 假设我们有一个32位的整数&#xff0c;其中不同的位代表不同的标志。例如&#xff1a; 位0&#xff1a;是否开启日志&#xff08;0表示关闭&#xff0c;1表示开启&#xff09; 位1&#xff1a;是否启用调试模式&#xff08;0表示禁用&#…...

高性能网络优化:深入解析忙轮询(Busy Polling)技术

在现代高性能网络应用中,如何降低数据包处理延迟、提升吞吐量是开发者与系统工程师的核心挑战之一。传统的“中断驱动”模式在高负载场景下表现不佳,而忙轮询(Busy Polling) 作为一种优化技术,通过主动轮询机制显著改善网络性能。本文将从原理、实现到实践,全面解析忙轮询…...

Linux grep 命令详解及示例大全

文章目录 一、基本语法二、常用选项及示例1. 基本匹配&#xff1a;查找包含某字符串的行2. 忽略大小写匹配 -i3. 显示行号 -n4. 递归查找目录下的文件 -r 或 -R5. 仅显示匹配的字符串 -o6. 使用正则表达式 -E&#xff08;扩展&#xff09;或 egrep7. 显示匹配前后行 -A, -B, -C…...

前端知识-hook

React 的生命周期管理被称为 Hook 技术&#xff0c;源于其设计哲学与实现机制中“钩入”组件运行流程的特性。这一命名既是对传统编程中“钩子”&#xff08;Hook&#xff09;概念的延伸&#xff0c;也体现了 React 对函数式组件的逻辑注入能力。以下从多个维度解析其关联性&am…...

uv全功能更新:统一管理Python项目、工具、脚本和环境的终极解决方案

花下猫语&#xff1a;uv 项目自发布起就大受欢迎&#xff0c;目前 Github star 52.6 K&#xff0c;远超过它的同类竞品们。前不久&#xff0c;它的创始人在 X 上披露了一组惊人的数据&#xff1a;uv 曾占据了 PyPI 超过 20% 的流量&#xff0c;用户每天通过它发起约 4-5 亿次下…...

Redis 使用及命令操作

文章目录 一、基本命令二、redis 设置键的生存时间或过期时间三、SortSet 排序集合类型操作四、查看中文五、密码设置和查看密码的方法六、关于 Redis 的 database 相关基础七、查看内存占用 一、基本命令 # 查看版本 redis-cli --version 结果&#xff1a;redis-cli 8.0.0red…...

ROS2:自定义接口文件(无废话)

目录 一、ROS2接口文件定义二、创建接口文件步骤三、验证是否创建成功&#xff0c;以及自定义接口文件的使用 一、ROS2接口文件定义 ROS2中接口文件的格式根据通信的类型可以分为三种&#xff1a; 话题通信&#xff1a;.msg文件 常用格式为&#xff1a;[消息类型] 消息名称 #话…...