47.Redis学习笔记
小林coding -> 图解redis的学习笔记
文章目录
- Redis
- windwos安装
- docker安装redis
- 启动redis
- 使用RDM访问虚拟机中的redis
- python连接redis
- 缓存穿透、击穿、雪崩
- 基本数据类型
- 高级数据类型
- 高并发指标
- 布隆过滤器
- 分布式锁
- Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?
- 跳表
- Bitmap的使用
- Redis线程模型
- Reactor 网络模型
- 四种常见的IO模型,BIO、NIO、AIO
- select/epoll
- Redis内存管理
- RDB和AOF
- Redis持久化
- Redis集群
- Redis为什么要给key设置过期时间
- 设置key过期时间的策略
- Redis过期删除与内存淘汰
- Redis缓存设计
- Redis实现延迟队列
- Redis的大key如何处理
- Redis 管道有什么用?
- Redis 事务支持回滚吗?
- 如何用 Redis 实现分布式锁的?
- Redis 如何解决集群情况下分布式锁的可靠性?
- Redis + lua脚本示例
- Redis 大 Key 对持久化有什么影响?
- 主从复制是怎么实现的?
- repl_backlog_buffer和replication buffer的区别
- repl_backlog_buffer
- replication buffer
- 区别总结
- 哨兵机制
- 数据库和缓存如何保证一致性?
- Redis解决可能出现的并发问题
- Redis的扩容机制
Redis
windwos安装
参考:[csdn]
docker安装redis
参考:[csdn] [zhihu]
启动redis
sudo docker run -p 6379:6379 --name redis --restart=always -v /home/mkid/software/redis/data:/data -v /home/mkid/software/redis/redis2.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf
vm.overcommit_memory = 1
#任何ip可以访问
bind 0.0.0.0
#守护进程
#daemonize yes
daemonize yes
#不启用保护模式
protected-mode no
#指定redis运行的端口
port 6379
tcp-backlog 511
timeout 0
#持久化⽂件名称
dbfilename xdclass.rdb
#持久化⽂件存储路径
dir /data/
#持久化策略, 10秒内有个1个key改动,执⾏快照
save 10 1
######之前配置######
#导出rdb数据库⽂件压缩字符串和对象,默认是yes,会浪费CPU但是节省空间
rdbcompression yes
# 导⼊时是否检查
rdbchecksum yes
#aof持久化配置
#appendonly yes
#appendfilename "appendonly.aof"
#appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
# yes表示如果aof尾部⽂件出问题,写log记录并继续执⾏。
# no表示提示写⼊等待修复后写⼊
aof-load-truncated yes
WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
这个警告是关于系统内存过度分配的设置。在 Redis 中,如果系统的内存过度分配未启用,可能会在低内存条件下导致后台保存或复制失败。即使没有低内存条件,也可能导致一些问题。
要解决这个问题,您需要将系统的内存过度分配设置为启用。您可以按照警告中提到的步骤执行:
-
添加下面这行到
/etc/sysctl.conf
文件中:vm.overcommit_memory = 1
您可以使用文本编辑器(如 nano 或 vim)以管理员权限打开该文件,并添加这一行到文件的底部。
-
重新加载 sysctl 配置以使更改生效:
sudo sysctl -p
这将重新加载 sysctl.conf 文件中的配置,并且使 vm.overcommit_memory
设置生效。
请注意,在生产环境中,特别是在修改系统级配置之前,请确保了解这些更改的含义,并确保它们不会对系统的稳定性和安全性产生不利影响。
使用RDM访问虚拟机中的redis
RDF连接虚拟机里的Redis:https://blog.csdn.net/qq_39535807/article/details/106449156
python连接redis
redis_client = redis.StrictRedis(host="localhost",port=6379,db=2,decode_responses=True
)
缓存穿透、击穿、雪崩
参考:[zhihu]
穿透:恶意绕过缓存和数据库中都没有的数据。(黑名单、缓存空值、布隆过滤器)
击穿:热点key失效,访问热点的大量请求直接打到数据库上。(互斥锁、异步更新缓存、不设置过期时间)
雪崩:大量缓存key失效,大量请求直接达到数据库上。(大量数据同时过期:均匀设置过期时间、客户端访问互斥锁、后台更新缓存2种、缓存预热。Redis宕机:熔断和限流、集群)
基本数据类型
Redis 支持的基本数据类型主要有五种,分别是:
-
字符串(String): Redis 的字符串是二进制安全的,这意味着它们可以包含任何数据,比如 jpg 图片或者序列化的对象。一个字符串类型的值最多可以是 512MB。
-
哈希(Hash): Redis 哈希是键值对集合。Redis 哈希是字符串字段和字符串值之间的映射,因此它们是适合用来表示对象的理想选择。
-
列表(List): Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
-
集合(Set): Redis 集合是字符串类型的无序集合。它是通过哈希表实现的,所以添加、删除、查找的复杂度都是 O(1)。
-
有序集合(Sorted Set): Redis 有序集合和集合一样也是字符串类型的集合,不同的是每个元素都会关联一个浮点数类型的分数。Redis 正是通过分数来为集合中的成员进行从小到大的排序。由于是通过分数进行排序,所以即使是在有相同分数的情况下,成员也会根据二进制顺序进行排序。不过,由于存在分数,你可以非常快速地获取一个分数范围内的成员,这个操作的复杂度是 O(log(N))。
Sorted Set的使用:[]
这些数据类型为 Redis 的使用提供了极大的灵活性,使其不仅仅能够被用作简单的键值存储,还可以用来实现复杂的数据结构服务器方案。
高级数据类型
除了前面提到的五种基本数据类型之外,Redis 还支持以下几种数据类型和特殊的数据结构:
-
HyperLogLog: 主要用于高效的基数统计,其核心优势在于,在使用极小的内存空间时,能够处理大量数据的基数估计问题。HyperLogLog 提供了一种不精确的去重计数方案,适用于大规模数据的去重计数,如统计网站访问量中的独立访客数。
基数统计介绍:[csdn]
-
地理位置(Geospatial): Redis 的地理位置类型允许你将用户定义的经纬度信息存储到 Redis 中,并可以进行地理位置相关的操作,比如计算两点之间的距离、查找某个半径内的点等。这是通过 Redis 的 Sorted Set 数据类型实现的,但提供了专门的命令来处理地理空间信息。
-
流(Streams): 引入于 Redis 5.0,流是 Redis 的一个更加复杂的数据类型,设计用来存储一系列的消息。流可以被认为是一个日志类型的数据结构,可用于存储一系列的事件或消息。流使得 Redis 能够更好地用于消息队列的应用场景,支持多播、持久化、消息确认等特性。
这些数据类型和结构提供了更多的使用场景和可能性,让 Redis 不仅仅是一个简单的键值存储系统,而是一个多功能的数据结构服务器,能够支持各种各样的应用场景。
高并发指标
参考:[zhihu]
布隆过滤器
参考:[csdn]
分布式锁
Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?
跳表
参考:[csdn]
Bitmap的使用
java guide 统计活跃用户:
这段 Redis 命令使用了 SETBIT
操作,它是一个位操作命令,用于设置字符串值的指定位(bit)的值。这个命令通常用于实现位数组,可以高效地存储和操作大量的布尔值(比如标记、开关状态等)。命令的格式如下:
SETBIT key offset value
key
是你想要操作的键。offset
是位的位置(从 0 开始计数)。value
只能是 1 或 0,代表你想要设置的位的值。
对于你给出的命令:
SETBIT 20210308 1 1
:在键20210308
上,将位于位置 1 的位设置为 1。SETBIT 20210308 2 1
:在键20210308
上,将位于位置 2 的位设置为 1。SETBIT 20210309 1 1
:在键20210309
上,将位于位置 1 的位设置为 1。
每个命令的返回值 (integer) 0
表示在执行操作之前,指定的位的原始值是 0。如果原始值已经是 1,则命令会返回 1。这里,所有命令的返回值都是 0,说明在这些操作执行之前,所有指定的位都是 0。
这种类型的操作非常适合于记录和查询标记或者状态,例如记录用户的登录天数,或者标记某个特定的功能是否对用户可见。它能够以非常紧凑和高效的方式处理大量的布尔值。
这两个 Redis 命令使用了 BITOP
和 BITCOUNT
操作,分别用于对位进行逻辑运算和统计设置为 1 的位的数量。下面是对这两个命令的解释:
BITOP
BITOP operation destkey key [key ...]
operation
是要执行的位操作,可以是AND
、OR
、XOR
、NOT
。destkey
是存储操作结果的键。key
是参与操作的一个或多个键。
在你的例子中:
BITOP and desk1 20210308 20210309
这个命令执行了一个 AND
位操作,将键 20210308
和 20210309
的值进行按位与操作,并将结果存储在 desk1
中。返回值 (integer) 1
表示结果键 desk1
现在有 1 个字节的长度。
BITCOUNT
BITCOUNT key [start end]
key
是要计算的键。start
和end
参数(可选)定义了要统计的字节范围。
对于你的第二个命令:
BITCOUNT desk1
这个命令统计了 desk1
中设置为 1 的位的数量。返回值 (integer) 1
表示在 desk1
的值中,有 1 个位被设置为了 1。
结合你之前的 SETBIT
命令,我们可以推断出 20210308
和 20210309
在至少一个相同的位置上都设置了位为 1,因此 AND
操作后,desk1
中也至少有一个位是 1。BITCOUNT
命令的结果进一步确认了这一点,只有一个位被设置为 1。
这种操作通常用于处理和分析大量的布尔数据,例如统计多个事件共同发生的次数或者进行集合的交集操作。
Redis线程模型
单线程模型。
为什么引入多线程?(提高网络IO的并行度)
后台线程?(lazyfree 线程、unlink key / flushdb async / flushall async)
unlink异步删除大key。
在linux系统中,所有服务都是文件。在图片的最上方,客户端的每个连接都是一个socket连接(socket文件),epoll
系统调用的作用是多路监听文件标识符发生变化,所以当某个客户端的socket连接(文件)发生变化时,epoll_wait
会检测到,触发事件分发器,执行后续的任务。
Reactor 网络模型
参考:[掘金]
IO多路复用(select/epoll)和事件驱动(异步IO的回调函数)。
IO读写涉及到用户态和内核态的转变。
单线程模型。(建立连接、数据读写都是一个线程)
多线程模型。(连接建立、IO事件读写、事件分发是一个线程,数据读写完之后,提交业务到线程池中处理)
主从线程模型。(主Reactor负责建立新连接、从Reactor负责IO读写事件-线程池/事件分发)
四种常见的IO模型,BIO、NIO、AIO
参考:[csdn]
同步阻塞IO(BIO)、同步非阻塞IO(NIO)、IO多路复用、异步IO(AIO)。
select/epoll
select
和 epoll
都是用于处理多个文件描述符的输入/输出准备就绪的I/O多路复用机制。它们使得单个进程/线程可以监视多个文件描述符,以便知道是否有I/O操作可以执行,这对于实现高性能的网络服务尤其重要。
select
select
是最早的I/O多路复用接口之一,它允许程序监视多个文件描述符,等待一个或多个文件描述符成为“就绪”状态,也就是说数据可读、可写或出现异常。它的基本原理是:
- 当你有多个文件描述符(比如套接字)需要同时监视时,你可以使用
select
函数。 - 你需要提供三个集合:读集合、写集合和异常集合,以及一个最大等待时间。
select
会阻塞当前线程,直到以下几种情况之一发生:- 至少有一个文件描述符就绪(对应的操作可以无阻塞地进行)。
- 发生一个信号中断。
- 超出了指定的最大等待时间。
select
的缺点是它支持的文件描述符数量有限(通常受限于1024),并且随着监视的文件描述符数量增加,性能会线性下降。
epoll
epoll
是在Linux 2.6及其以后版本中引入的,作为select
和poll
的现代替代品。epoll
解决了select
的一些主要限制,尤其是在处理大量文件描述符时的性能问题。它的特点包括:
- 支持的文件描述符数量远大于1024。
- 使用一种更高效的机制来通知哪些文件描述符就绪,这意味着不需要像
select
那样在每次调用时重新指定整个文件描述符集合。 - 支持“边缘触发”和“水平触发”两种工作模式,使其更加灵活。
epoll
通过创建一个epoll
实例,然后向这个实例中添加或删除文件描述符来工作。当调用epoll_wait
时,它会返回自上次调用以来变为就绪状态的文件描述符,这种方式比select
的轮询效率更高。
总结而言,epoll
相对于select
,在处理大量并发连接时具有更高的效率和更好的可扩展性,因此成为了高性能网络服务器编程的首选技术之一。
Redis内存管理
RDB和AOF
参考:[zhihu]
Redis持久化
AOF刷盘和RDB快照。
aof的重写。(后台子进程:bgrewriteaof)
rdb的save个bgsave。
Redis集群
redis的三种集群方式,脑裂导致的数据丢失。
Redis为什么要给key设置过期时间
在Redis中设置键(key)的过期时间是一项非常重要的功能,主要基于以下几个理由:
-
内存管理:Redis是一个基于内存的存储系统,尽管它可以将数据持久化到磁盘上,但其主要操作都是在内存中进行的。内存资源有限,因此有效地管理内存非常关键。通过为键设置过期时间,可以自动删除不再需要的数据,从而释放宝贵的内存资源。这是一种自动的内存清理机制,有助于避免内存被无限期地消耗。
-
数据有效性:在很多应用场景中,数据都有其有效期。例如,缓存数据可能只在很短的时间内是有效的,之后就变得陈旧了;会话(session)数据在用户退出或会话超时后不再需要。为这些数据设置过期时间,可以确保数据的新鲜度和相关性,当数据过期后,Redis会自动将其删除。
-
减少维护成本:如果没有自动的过期机制,应用开发者需要自己实现数据清理逻辑,这不仅增加了开发的复杂性,还可能会导致程序效率降低,因为应用层面的数据清理通常不如Redis内部机制来得高效和可靠。
-
优化性能:通过删除过期的键来释放内存空间,可以保持Redis数据库的高性能。过多的冗余数据会降低数据操作的效率,尤其是在进行键的查找、数据的读写等操作时。保持数据集的紧凑可以提高操作效率,减少延迟。
-
支持特定应用逻辑:有些应用场景本身就需要基于时间的自动逻辑处理,比如临时访问令牌的过期处理、限时活动的数据管理等。Redis的过期时间功能天然支持这类需求,使得开发这类功能时更加简便和高效。
综上所述,设置键的过期时间是Redis管理内存、保证数据有效性、优化性能以及支持复杂应用逻辑的一个重要功能。这不仅减轻了开发者的负担,还提升了应用的整体性能和用户体验。
设置key过期时间的策略
在Redis中,设置键(key)的过期时间主要有以下几种策略:
-
设置固定过期时间:
EXPIRE key seconds
:为键设置过期时间,时间单位为秒。PEXPIRE key milliseconds
:为键设置过期时间,时间单位为毫秒。
这两个命令都是在设置键的过期时间时指定一个具体的时间长度,键会在指定的时间后自动被删除。
-
设置具体过期的时间点:
EXPIREAT key timestamp
:将键的过期时间设置为UNIX时间戳表示的某一具体时间点,单位为秒。PEXPIREAT key millisecondsTimestamp
:将键的过期时间设置为UNIX时间戳表示的某一具体时间点,单位为毫秒。
使用这两个命令可以设置键在某个具体的时间点过期,而不是从当前时间开始计算的一个时间段。
-
设置键在不活动(idle)状态下的过期时间:
-
Redis默认不支持基于不活动时间的自动过期策略。不过,可以通过自定义脚本或应用逻辑来模拟这种行为,比如定期检查键的最后访问时间,并删除那些超过特定不活动时间阈值的键。
Redis本身不直接支持根据键的不活动时间自动设置过期时间,但你可以通过一些额外的逻辑来模拟这种行为。这里给出一个简单的例子,演示如何利用Redis的现有命令和一些外部逻辑来实现基于不活动时间的键过期策略:
基本思路:
- 对于每个键,使用一个额外的键来记录最后一次访问时间。
- 定期运行一个脚本或任务,检查每个键的不活动时间。
- 如果某个键的不活动时间超过了预设的阈值,就删除该键。
实现步骤:
假设你有一个键
user:session:1234
,你想要在这个键30分钟内未被访问时自动删除它。步骤 1:设置最后访问时间键
每次访问
user:session:1234
时,同时设置或更新一个与之关联的键来记录访问时间。例如,可以用user:session:1234:last_access
作为记录最后访问时间的键。SET user:session:1234 "some data" SET user:session:1234:last_access `current unix timestamp`
步骤 2:定期检查不活动时间
编写一个脚本或在应用中实现逻辑,定期执行以下步骤:
- 获取当前时间的UNIX时间戳。
- 对于每个会话键,获取其
last_access
键的值。 - 计算当前时间与最后访问时间的差值。
- 如果差值超过了预设的不活动阈值(例如,1800秒表示30分钟),则删除该会话键及其
last_access
键。
示例脚本逻辑(伪代码):
current_time = get_current_unix_timestamp() keys = get_all_session_keys() # 获取所有会话键for key in keys:last_access_key = key + ":last_access"last_access_time = get_value(last_access_key) # 获取最后访问时间if current_time - last_access_time > 1800: # 30分钟不活动delete_key(key) # 删除会话键delete_key(last_access_key) # 删除最后访问时间键
步骤 3:自动化执行检查任务
你可以使用cron作业(Linux)、计划任务(Windows)或者Redis自身的定时功能(如果通过Lua脚本实现)来定期执行上述检查脚本。
这个方法虽然不能直接通过Redis命令实现不活动过期,但通过外部逻辑的辅助,可以满足需求。需要注意的是,这种方法可能会增加服务器负载,并且在高并发场景下需要谨慎处理并发访问和更新
last_access
键的情况。
-
-
使用TTL命令查询剩余过期时间:
TTL key
:查询键的剩余过期时间(秒)。PTTL key
:查询键的剩余过期时间(毫秒)。
这不是设置过期时间的策略,但与管理键的过期时间密切相关,可以帮助你了解键的当前过期状态。
-
移除过期时间:
PERSIST key
:移除键的过期时间,使其变成一个永久键。
如果之前为键设置了过期时间,但后来决定让该键持久存储,可以使用这个命令移除其过期时间。
-
设置键值与过期时间:
- 在设置键值的同时设置过期时间,这可以通过
SET
命令的选项来完成,如SET key value EX seconds
或SET key value PX milliseconds
,这可以减少命令的发送次数,提高效率。
- 在设置键值的同时设置过期时间,这可以通过
选择合适的过期时间策略取决于你的具体需求和场景。例如,对于缓存数据,通常会使用固定的过期时间;而对于需要在特定时间点过期的数据(比如临时活动信息),则会设置具体过期的时间点。
Redis过期删除与内存淘汰
过期键的删除:过期字典。惰性删除+定时删除+定期删除。
持久化时,对过期的键如何处理:RDB阶段、AOF阶段。
主从模式的过期键处理。
内存淘汰策略:不进行数据淘汰、进行数据淘汰。
进行数据淘汰:设置了过期时间的淘汰、没设置过期时间淘汰。
Redis缓存设计
雪崩、击穿、穿透。
动态缓存热点。zset(zadd, zrange)
常见的缓存更新策略。(旁路缓存、读穿/写穿缓存、写回策略-不用)
Redis实现延迟队列
zset。
Redis的大key如何处理
String 类型的值大于 10 KB;
Hash、List、Set、ZSet 类型的元素的个数超过 5000个;
1、redis-cli --bigkeys 查找大key
2、使用 SCAN 命令查找大 key
3、使用 RdbTools 工具查找大 key
删除
分批次删除
异步删除(Redis 4.0版本以上)(小林coding)
Redis 管道有什么用?
Redis 事务支持回滚吗?
支持。只支持命令的回滚,不保证事务的原子性。
如何用 Redis 实现分布式锁的?
setnx + 过期时间。
优缺点。
Redis 如何解决集群情况下分布式锁的可靠性?
Redlock(红锁)。
Redis + lua脚本示例
Redis 支持使用 Lua 脚本来执行复杂的操作,这允许你在 Redis 服务器端执行一系列命令,而无需往返于客户端和服务器之间,从而提高效率。下面是一个使用 Lua 脚本操作 Redis 集合(Set)的示例。
假设我们要编写一个 Lua 脚本,这个脚本的目标是:
- 向一个集合中添加一些值。
- 从另一个集合中移除一些值。
- 返回第一个集合的所有成员。
在 Redis 中,我们可以使用 SADD
命令来添加元素到集合中,使用 SREM
命令来从集合中移除元素,使用 SMEMBERS
命令来获取集合的所有成员。
Lua 脚本示例:
-- 定义要操作的集合的键和要添加或移除的值
local addSetKey = KEYS[1]
local removeSetKey = KEYS[2]
local addValues = ARGV[1]
local removeValues = ARGV[2]-- 向 addSetKey 集合中添加元素
for value in string.gmatch(addValues, "%S+") doredis.call('SADD', addSetKey, value)
end-- 从 removeSetKey 集合中移除元素
for value in string.gmatch(removeValues, "%S+") doredis.call('SREM', removeSetKey, value)
end-- 返回 addSetKey 集合的所有成员
return redis.call('SMEMBERS', addSetKey)
在这个脚本中,KEYS[1]
和 KEYS[2]
是 Redis 键名参数,ARGV[1]
和 ARGV[2]
是传递给脚本的值参数。string.gmatch
函数用于迭代参数中的每个值(假设值由空格分隔)。
使用该脚本的命令可能如下(示例):
redis-cli --eval script.lua mySet1 mySet2 , "value1 value2 value3" "value4 value5"
在这个命令中,mySet1
和 mySet2
是操作的集合键,"value1 value2 value3"
是要添加到 mySet1
的值,"value4 value5"
是要从 mySet2
移除的值。请注意,逗号后面是 ARGV
参数的开始。
请记住,你需要将 script.lua
替换为你的 Lua 脚本文件的实际路径,或者你可以直接在命令行中使用 EVAL
命令并直接传递 Lua 脚本的内容(而不是文件路径)。
Redis 大 Key 对持久化有什么影响?
从aof和rdb两个方面说明。
主从复制是怎么实现的?
确定主服务器和从服务器。
第一次同步,三个阶段(全量复制)。(从 psync-> 主,主 FULLRESYNC-> 从,主rdb -> 从,主写入缓存 -> 从)。
命令传播(TCP长连接)。
从服务器(经理服务器)。
增量复制。(repl_backlog_buffer + replication offset)
repl_backlog_buffer和replication buffer的区别
这两个都在主服务器上。
repl_backlog_buffer
和replication buffer
是Redis复制机制中的两个重要组件,它们在Redis的数据复制过程中扮演着关键的角色。尽管这两个组件在功能上有所重叠,它们的主要目的和使用场景有所不同。以下是它们各自的概述和区别:
repl_backlog_buffer
- 目的:
repl_backlog_buffer
主要用于支持部分复制功能。它是一个固定大小的缓冲区,用于保存最近的写命令。当一个从服务器与主服务器失去连接并稍后重新连接时,它可以请求这个缓冲区中保存的命令来更新它丢失的数据,而不是进行全量复制。 - 特点:这个缓冲区是环形的,意味着当它满了以后,新的写命令会覆盖最老的命令。缓冲区的大小可以配置,从而影响Redis可以支持的网络分区恢复时间和从服务器断开时间。
- 使用场景:适用于网络不稳定或从服务器频繁断开连接的场景,在这些情况下,可以有效地减少数据同步的负担。
replication buffer
- 目的:
replication buffer
用于存储正在复制到一个或多个从服务器的数据。当从服务器连接到主服务器请求数据时,主服务器会使用这个缓冲区来暂存要发送的数据。 - 特点:与
repl_backlog_buffer
不同,replication buffer
的生命周期与复制会话相关联。它的大小根据需要动态调整,以适应当前的复制负载。当复制完成或取消时,相关的复制缓冲区将被清空。 - 使用场景:适用于全量复制的场景,比如当一个新的从服务器被添加到Redis集群中,或者一个从服务器因为故障或其它原因需要重新同步全部数据时。
区别总结
- 用途差异:
repl_backlog_buffer
用于支持部分复制,以减少因为网络问题或从服务器故障导致的数据重新同步需求;而replication buffer
用于在全量复制过程中暂存数据。 - 生命周期:
repl_backlog_buffer
是长期存在的,用于记录最近的写操作,其大小固定;而replication buffer
的生命周期与复制会话相关,大小根据复制需求动态调整。 - 配置和管理:两者的配置和管理也有所不同,反映了它们在Redis复制机制中的不同角色。
理解这两个组件及其区别有助于更好地管理和优化Redis的复制和数据同步机制。
哨兵机制
判断主节点故障。(哨兵ping -> 主/从)
主观下线(quorum法定人数)-> 客观下线。
哨兵leader。
主从故障转移。(三个过程)
主从节点切换。(四个步骤)
哨兵集群是如何组成的?(通过主节点的__sentinel__:hello
频道)
数据库和缓存如何保证一致性?
先更新数据库,还是先更新缓存?(都会出现数据不一致的情况)
先更新数据库,还是先删除缓存?(先更新数据库,再删除缓存可以保证一致性)
更新数据库和删除缓存两个分开进行,后者操作失败怎么办?(重试机制-消息队列、mysql binlog)
先删除缓存再更新数据库数据不一致。(延迟双删)
Redis解决可能出现的并发问题
Redis和Lua脚本结合可以有效地解决一些并发问题,尤其是在多个客户端同时访问Redis数据库时。下面是一个简单的示例,演示如何使用Redis和Lua脚本来解决并发问题:
假设我们有一个需求:多个客户端需要同时对某个计数器进行操作,但是我们希望保证在任何时刻,计数器的值都是正确的,而不会出现竞态条件。
首先,我们可以使用Redis的INCR和DECR命令来实现计数器的自增和自减操作。但是,如果多个客户端同时尝试修改计数器的值,就会出现竞态条件,导致结果不确定。
为了解决这个问题,我们可以使用Lua脚本来将自增和自减操作原子化。以下是一个简单的Lua脚本示例:
local counter_key = KEYS[1]
local action = ARGV[1]if action == "increment" thenreturn redis.call('INCR', counter_key)
elseif action == "decrement" thenreturn redis.call('DECR', counter_key)
elsereturn nil
end
然后,我们可以将这个Lua脚本保存到Redis中,并通过调用EVAL命令来执行它。在调用EVAL命令时,我们需要传递计数器的键名和要执行的操作作为参数。
以下是一个示例的Python代码,演示了如何使用Redis-py库在Python中调用Lua脚本:
import redis# 连接到Redis服务器
r = redis.Redis(host='localhost', port=6379, db=0)# 保存Lua脚本
lua_script = """
local counter_key = KEYS[1]
local action = ARGV[1]if action == "increment" thenreturn redis.call('INCR', counter_key)
elseif action == "decrement" thenreturn redis.call('DECR', counter_key)
elsereturn nil
end
"""# 执行Lua脚本
def execute_lua_script(counter_key, action):return r.eval(lua_script, 1, counter_key, action)# 使用示例
counter_key = 'my_counter'
print("Incrementing counter:", execute_lua_script(counter_key, 'increment'))
print("Decrementing counter:", execute_lua_script(counter_key, 'decrement'))
这样,无论多少个客户端同时尝试修改计数器的值,都可以保证操作的原子性,从而避免了竞态条件的发生。
Redis的扩容机制
Redis的扩容机制主要涉及增加更多的内存资源和提升处理能力,以应对数据增长和访问压力。这种扩容通常通过增加更多的Redis节点来实现,分为两种基本模式:分片(Sharding)和复制(Replication)。在更复杂的场景下,Redis Cluster提供了一种综合使用分片和复制的解决方案来实现扩容和高可用。
分片(Sharding)
分片是通过分散数据到多个Redis服务器来减轻单个服务器的负担,每个分片处理数据集的一部分。这样,每个Redis实例只需存储总数据集的一部分,从而可以水平扩展数据库的存储能力和处理能力。客户端库通常负责确定数据应该存储在哪个分片上,这通常是通过一致性哈希或其他哈希机制来实现的。
优点:
- 水平扩展:可以通过添加更多的Redis服务器来增加总体的存储容量和处理能力。
- 负载均衡:均匀分布数据和请求可以防止任何单个节点成为瓶颈。
缺点:
- 数据管理复杂性增加:需要确保数据均匀分布,避免某些节点过载。
- 跨节点操作受限:例如,对于需要同时处理多个键的操作,如果这些键分布在不同的节点上,将难以实现。
复制(Replication)
复制是指将数据从一个Redis服务器复制到一个或多个Redis服务器的过程,通常用于提高数据的可用性和读取性能。复制允许在主节点上进行写操作,而从节点提供读服务。在出现故障时,可以从从节点进行故障转移。
优点:
- 高可用性:如果主节点失败,从节点可以接管成为新的主节点,保证服务的可用性。
- 读扩展:可以通过增加更多的从节点来扩展读取能力。
缺点:
- 写操作不扩展:所有写操作都必须在主节点上执行,因此写能力的扩展受到限制。
- 数据延迟:从节点复制数据可能会有延迟。
Redis Cluster
Redis Cluster是一个提供自动分片和数据复制的Redis部署方案,旨在提供高性能、线性扩展性和高可用性。它通过自动将数据分散到多个节点(每个节点存储数据集的一部分)并在这些节点之间进行复制来实现这一点。
特点:
- 自动分片:数据自动分布在多个节点上,简化了分片管理。
- 高可用性:通过数据复制和故障转移机制,确保服务即使在节点故障时也能继续运行。
- 读写扩展:支持通过增加更多节点来扩展读写能力。
实施扩容
在实施Redis扩容时,应考虑以下因素:
- 数据迁移:当添加新的节点时,可能需要重新分配现有数据,这可能会暂时影响性能。
- 客户端支持:确保客户端库支持所选择的扩容方案,如自动分片支持或Redis Cluster。
- 监控和调整:扩容后需要监控系统性能并根据实际情况进行调整,以确保系统达到预期的性能和稳定性目标。
Redis的扩容机制提供了灵活的方案来应对不断增长的数据和请求负载,但实施时需要综
。复制允许在主节点上进行写操作,而从节点提供读服务。在出现故障时,可以从从节点进行故障转移。
优点:
- 高可用性:如果主节点失败,从节点可以接管成为新的主节点,保证服务的可用性。
- 读扩展:可以通过增加更多的从节点来扩展读取能力。
缺点:
- 写操作不扩展:所有写操作都必须在主节点上执行,因此写能力的扩展受到限制。
- 数据延迟:从节点复制数据可能会有延迟。
Redis Cluster
Redis Cluster是一个提供自动分片和数据复制的Redis部署方案,旨在提供高性能、线性扩展性和高可用性。它通过自动将数据分散到多个节点(每个节点存储数据集的一部分)并在这些节点之间进行复制来实现这一点。
特点:
- 自动分片:数据自动分布在多个节点上,简化了分片管理。
- 高可用性:通过数据复制和故障转移机制,确保服务即使在节点故障时也能继续运行。
- 读写扩展:支持通过增加更多节点来扩展读写能力。
实施扩容
在实施Redis扩容时,应考虑以下因素:
- 数据迁移:当添加新的节点时,可能需要重新分配现有数据,这可能会暂时影响性能。
- 客户端支持:确保客户端库支持所选择的扩容方案,如自动分片支持或Redis Cluster。
- 监控和调整:扩容后需要监控系统性能并根据实际情况进行调整,以确保系统达到预期的性能和稳定性目标。
Redis的扩容机制提供了灵活的方案来应对不断增长的数据和请求负载,但实施时需要综
相关文章:

47.Redis学习笔记
小林coding -> 图解redis的学习笔记 文章目录 Rediswindwos安装docker安装redis启动redis使用RDM访问虚拟机中的redispython连接redis缓存穿透、击穿、雪崩基本数据类型高级数据类型高并发指标布隆过滤器分布式锁Redis 的有序集合底层为什么要用跳表,而不用平衡…...

数控六面钻适用场景-不止家具制造
在快节奏的现代生活中,家具作为我们生活的重要组成部分,其美观度和实用性日益受到人们的关注。而在这背后,一个不可或缺的“工匠”正默默地发挥着它的作用——那就是数控六面钻。 数控六面钻,顾名思义,是一种高度自动…...
【力扣】86. 分隔链表
86. 分隔链表 题目描述 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示例 1: 输入:head […...

海云安受邀参加诸子云 4.27南京「金融互联网」私董会
4月27日,“安在新媒体网安用户行业活动”第四期私董会在南京顺利举办。活动以“金融&互联网”为主题,邀请十余位业内资深的甲方用户以及典型厂商代表。摒弃传统的议题分享,采取“随时问答,自由讨论”的形式,提问题…...
docker操作使用注意事项
文章目录 一、运行docker二、拉取的镜像存放位置1、查询所有拉取的镜像2、查询所有安装的镜像3、查询docker应用的所有信息 一、运行docker 该命令执行后是在窗口下运行的,关闭或退出后docker应用会停止运行 -p:设置绑定端口映射,10022对应…...

Leetcode—163. 缺失的区间【简单】Plus
2024每日刷题(126) Leetcode—163. 缺失的区间 实现代码 class Solution { public:vector<vector<int>> findMissingRanges(vector<int>& nums, int lower, int upper) {int n nums.size();vector<vector<int>> an…...

Ansible自动化运维工具 - playbook 剧本编写
一. inventory 主机清单 Inventory 支持对主机进行分组,每个组内可以定义多个主机,每个主机都可以定义在任何一个或多个主机组内。 1.1 inventory 中的变量含义 Inventory 变量名 含义ansible_hostansible连接节点时的IP地址ansible_port连接对方…...

Web前端一套全部清晰 ⑥ day4 CSS.2 复合选择器、CSS特性、背景属性、标签的显示模式
别人的议论,那是别人的,你的人生,才是你的 —— 24.5.7 一、复合选择器 定义:由两个或多个基础选择器,通过不同的方式组合而成 作用:更准确、更高效的选择目标元素(标签) 1.后代选择…...

Linux 认识与学习Bash——3
在Linux bash中,数据流重定向是指将命令的输出从默认的标准输出(通常是终端)重定向到其他位置,如文件或另一个命令的输入。这是通过使用特定的符号来实现的。例如,>用于将输出重定向到文件,而<用于将…...

匠心精神与创新力量:构筑网络安全的新防线
一、匠心精神在网络安全中的重要性 匠心精神代表着对工作的专注和对质量的极致追求。在网络安全领域,这意味着对每一个安全漏洞的深入挖掘,对每一项安全技术的精心打磨。亿林网络李璐昆的提名,正是对其在网络安全领域匠心精神的认可。 二、…...
接口信息解析
目录 一、通讯流程 二、如何获取接口信息--抓包 1、抓包步骤: 2、抓包工具 接口文档:又称为API文档,是由后端开发编写,用来描述接口信息的文档 一、通讯流程 功能(比如:登录)请求(请求路径、请求方式、…...

scikit-learn实现单因子线性回归模型
1.是什么: 针对机器学习提供了数据预处理,分类,回归等常见算法的框架 2.基于scikit-learn求解线性回归的问题: 2.1.求解a,b对新数据进行预测: 2.2评估模型表现(y和y’的方差MSE)…...

【笔记】Anaconda命令提示符(Anaconda Prompt)操作
通过anaconda配置python环境有时需要conda安装一些包或者文件,这里作为一个笔记记录如何打开Anaconda命令提示符(Anaconda Prompt),并用conda操作 1.打开Anaconda命令提示符(Anaconda Prompt) 可直接在搜…...

Unity射击游戏开发教程:(12)使用后处理
后处理 后期处理是向您的游戏场景添加一个或多个滤镜,确实可以为您的游戏提供精美的外观。在本文中,我们将讨论如何在 Unity 中设置后处理系统,从那里您可以探索和试验 Unity 提供的所有过滤器。 首先,我们需要从包管理器添加后处理器堆栈。包管理器是 Unity 产品的集合,…...

python:机器学习特征优选
作者:CSDN _养乐多_ 在Python中进行机器学习特征选择的方法有很多种。以下是一些常用的方法: 过滤法(Filter Methods):通过统计方法或者相关性分析来评估每个特征的重要性,然后选择最相关的特征。常用的…...
花一个月时间为 vue3 重制了 vue-styled-components
花一个月时间为 vue3 重制了 vue-styled-components 前言 styled-components 在 React 是一个超级热门的 css in js 工具库。其实 styled-components 也有 Vue 版本(vue-styled-components),可惜的是只支持 Vue2,并且该项目已有…...

API接口调用|京东API接口|淘宝API接口
什么是电商API接口: 电商API接口是电商服务平台对外提供的一种接口服务,允许第三方开发者通过编程方式与电商系统进行数据交互和功能调用。 这些接口提供了一种标准化的方法来获取、更新或处理电商平台上的商品信息、订单状态、用户数据、支付信息、物流…...
pgsql和mysql比较
pgsql相对于mysql的优势主要体现在以下几个方面: 稳定性和可靠性:PostgreSQL的稳定性极强,即使在崩溃、断电等灾难场景下也能表现出很好的抗打击能力。相比之下,很多MySQL用户都遇到过Server级的数据库丢失的情况。此外ÿ…...
【太赫兹偏振保持亚波长波导链路功率预算分析】
在进行太赫兹(Terahertz,THz)偏振保持亚波长波导链路的功率预算分析时,我们需要考虑多个因素,包括波导的传输损耗、耦合损耗、偏振保持性能、以及可能存在的其他系统损耗。以下是一个基本的分析框架: 传输…...

json-server的安装和使用
json-server介绍 json-server是可以把本地当做服务器,然后axios向本地区发送请求,并且不会出现跨域的问题,若是等不及后端数据,可以用这个模拟假数据 json-server安装及使用 【json-server网址】https://www.npmjs.com/package/…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...

《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
Nginx1.24编译时,报LuaJIT2.x错误, configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...