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 中,如果系统的内存过度分配未启用,可能会在低内存条件下导致后台保存或复制失败。即使没有低内存条件,也可能导致一些问题。

要解决这个问题,您需要将系统的内存过度分配设置为启用。您可以按照警告中提到的步骤执行:

  1. 添加下面这行到 /etc/sysctl.conf 文件中:

    vm.overcommit_memory = 1
    

    您可以使用文本编辑器(如 nano 或 vim)以管理员权限打开该文件,并添加这一行到文件的底部。

  2. 重新加载 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 支持的基本数据类型主要有五种,分别是:

  1. 字符串(String): Redis 的字符串是二进制安全的,这意味着它们可以包含任何数据,比如 jpg 图片或者序列化的对象。一个字符串类型的值最多可以是 512MB。

  2. 哈希(Hash): Redis 哈希是键值对集合。Redis 哈希是字符串字段和字符串值之间的映射,因此它们是适合用来表示对象的理想选择。

  3. 列表(List): Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

  4. 集合(Set): Redis 集合是字符串类型的无序集合。它是通过哈希表实现的,所以添加、删除、查找的复杂度都是 O(1)。

  5. 有序集合(Sorted Set): Redis 有序集合和集合一样也是字符串类型的集合,不同的是每个元素都会关联一个浮点数类型的分数。Redis 正是通过分数来为集合中的成员进行从小到大的排序。由于是通过分数进行排序,所以即使是在有相同分数的情况下,成员也会根据二进制顺序进行排序。不过,由于存在分数,你可以非常快速地获取一个分数范围内的成员,这个操作的复杂度是 O(log(N))。

    Sorted Set的使用:[]

这些数据类型为 Redis 的使用提供了极大的灵活性,使其不仅仅能够被用作简单的键值存储,还可以用来实现复杂的数据结构服务器方案。

高级数据类型

除了前面提到的五种基本数据类型之外,Redis 还支持以下几种数据类型和特殊的数据结构:

  1. HyperLogLog: 主要用于高效的基数统计,其核心优势在于,在使用极小的内存空间时,能够处理大量数据的基数估计问题。HyperLogLog 提供了一种不精确的去重计数方案,适用于大规模数据的去重计数,如统计网站访问量中的独立访客数。

    基数统计介绍:[csdn]

  2. 地理位置(Geospatial): Redis 的地理位置类型允许你将用户定义的经纬度信息存储到 Redis 中,并可以进行地理位置相关的操作,比如计算两点之间的距离、查找某个半径内的点等。这是通过 Redis 的 Sorted Set 数据类型实现的,但提供了专门的命令来处理地理空间信息。

  3. 流(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,代表你想要设置的位的值。

对于你给出的命令:

  1. SETBIT 20210308 1 1:在键 20210308 上,将位于位置 1 的位设置为 1。
  2. SETBIT 20210308 2 1:在键 20210308 上,将位于位置 2 的位设置为 1。
  3. SETBIT 20210309 1 1:在键 20210309 上,将位于位置 1 的位设置为 1。

每个命令的返回值 (integer) 0 表示在执行操作之前,指定的位的原始值是 0。如果原始值已经是 1,则命令会返回 1。这里,所有命令的返回值都是 0,说明在这些操作执行之前,所有指定的位都是 0。

这种类型的操作非常适合于记录和查询标记或者状态,例如记录用户的登录天数,或者标记某个特定的功能是否对用户可见。它能够以非常紧凑和高效的方式处理大量的布尔值。

这两个 Redis 命令使用了 BITOPBITCOUNT 操作,分别用于对位进行逻辑运算和统计设置为 1 的位的数量。下面是对这两个命令的解释:

BITOP

BITOP operation destkey key [key ...]
  • operation 是要执行的位操作,可以是 ANDORXORNOT
  • destkey 是存储操作结果的键。
  • key 是参与操作的一个或多个键。

在你的例子中:

BITOP and desk1 20210308 20210309

这个命令执行了一个 AND 位操作,将键 2021030820210309 的值进行按位与操作,并将结果存储在 desk1 中。返回值 (integer) 1 表示结果键 desk1 现在有 1 个字节的长度。

BITCOUNT

BITCOUNT key [start end]
  • key 是要计算的键。
  • startend 参数(可选)定义了要统计的字节范围。

对于你的第二个命令:

BITCOUNT desk1

这个命令统计了 desk1 中设置为 1 的位的数量。返回值 (integer) 1 表示在 desk1 的值中,有 1 个位被设置为了 1。

结合你之前的 SETBIT 命令,我们可以推断出 2021030820210309 在至少一个相同的位置上都设置了位为 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

selectepoll 都是用于处理多个文件描述符的输入/输出准备就绪的I/O多路复用机制。它们使得单个进程/线程可以监视多个文件描述符,以便知道是否有I/O操作可以执行,这对于实现高性能的网络服务尤其重要。

select

select是最早的I/O多路复用接口之一,它允许程序监视多个文件描述符,等待一个或多个文件描述符成为“就绪”状态,也就是说数据可读、可写或出现异常。它的基本原理是:

  • 当你有多个文件描述符(比如套接字)需要同时监视时,你可以使用select函数。
  • 你需要提供三个集合:读集合、写集合和异常集合,以及一个最大等待时间。
  • select会阻塞当前线程,直到以下几种情况之一发生:
    • 至少有一个文件描述符就绪(对应的操作可以无阻塞地进行)。
    • 发生一个信号中断。
    • 超出了指定的最大等待时间。

select的缺点是它支持的文件描述符数量有限(通常受限于1024),并且随着监视的文件描述符数量增加,性能会线性下降。

epoll

epoll是在Linux 2.6及其以后版本中引入的,作为selectpoll的现代替代品。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)的过期时间是一项非常重要的功能,主要基于以下几个理由:

  1. 内存管理:Redis是一个基于内存的存储系统,尽管它可以将数据持久化到磁盘上,但其主要操作都是在内存中进行的。内存资源有限,因此有效地管理内存非常关键。通过为键设置过期时间,可以自动删除不再需要的数据,从而释放宝贵的内存资源。这是一种自动的内存清理机制,有助于避免内存被无限期地消耗。

  2. 数据有效性:在很多应用场景中,数据都有其有效期。例如,缓存数据可能只在很短的时间内是有效的,之后就变得陈旧了;会话(session)数据在用户退出或会话超时后不再需要。为这些数据设置过期时间,可以确保数据的新鲜度和相关性,当数据过期后,Redis会自动将其删除。

  3. 减少维护成本:如果没有自动的过期机制,应用开发者需要自己实现数据清理逻辑,这不仅增加了开发的复杂性,还可能会导致程序效率降低,因为应用层面的数据清理通常不如Redis内部机制来得高效和可靠。

  4. 优化性能:通过删除过期的键来释放内存空间,可以保持Redis数据库的高性能。过多的冗余数据会降低数据操作的效率,尤其是在进行键的查找、数据的读写等操作时。保持数据集的紧凑可以提高操作效率,减少延迟。

  5. 支持特定应用逻辑:有些应用场景本身就需要基于时间的自动逻辑处理,比如临时访问令牌的过期处理、限时活动的数据管理等。Redis的过期时间功能天然支持这类需求,使得开发这类功能时更加简便和高效。

综上所述,设置键的过期时间是Redis管理内存、保证数据有效性、优化性能以及支持复杂应用逻辑的一个重要功能。这不仅减轻了开发者的负担,还提升了应用的整体性能和用户体验。

设置key过期时间的策略

在Redis中,设置键(key)的过期时间主要有以下几种策略:

  1. 设置固定过期时间

    • EXPIRE key seconds:为键设置过期时间,时间单位为秒。
    • PEXPIRE key milliseconds:为键设置过期时间,时间单位为毫秒。
      这两个命令都是在设置键的过期时间时指定一个具体的时间长度,键会在指定的时间后自动被删除。
  2. 设置具体过期的时间点

    • EXPIREAT key timestamp:将键的过期时间设置为UNIX时间戳表示的某一具体时间点,单位为秒。
    • PEXPIREAT key millisecondsTimestamp:将键的过期时间设置为UNIX时间戳表示的某一具体时间点,单位为毫秒。
      使用这两个命令可以设置键在某个具体的时间点过期,而不是从当前时间开始计算的一个时间段。
  3. 设置键在不活动(idle)状态下的过期时间

    • Redis默认不支持基于不活动时间的自动过期策略。不过,可以通过自定义脚本或应用逻辑来模拟这种行为,比如定期检查键的最后访问时间,并删除那些超过特定不活动时间阈值的键。

      Redis本身不直接支持根据键的不活动时间自动设置过期时间,但你可以通过一些额外的逻辑来模拟这种行为。这里给出一个简单的例子,演示如何利用Redis的现有命令和一些外部逻辑来实现基于不活动时间的键过期策略:

      基本思路:

      1. 对于每个键,使用一个额外的键来记录最后一次访问时间。
      2. 定期运行一个脚本或任务,检查每个键的不活动时间。
      3. 如果某个键的不活动时间超过了预设的阈值,就删除该键。

      实现步骤:

      假设你有一个键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键的情况。

  4. 使用TTL命令查询剩余过期时间

    • TTL key:查询键的剩余过期时间(秒)。
    • PTTL key:查询键的剩余过期时间(毫秒)。
      这不是设置过期时间的策略,但与管理键的过期时间密切相关,可以帮助你了解键的当前过期状态。
  5. 移除过期时间

    • PERSIST key:移除键的过期时间,使其变成一个永久键。
      如果之前为键设置了过期时间,但后来决定让该键持久存储,可以使用这个命令移除其过期时间。
  6. 设置键值与过期时间

    • 在设置键值的同时设置过期时间,这可以通过SET命令的选项来完成,如SET key value EX secondsSET 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 脚本,这个脚本的目标是:

  1. 向一个集合中添加一些值。
  2. 从另一个集合中移除一些值。
  3. 返回第一个集合的所有成员。

在 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"

在这个命令中,mySet1mySet2 是操作的集合键,"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_bufferreplication 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的扩容机制提供了灵活的方案来应对不断增长的数据和请求负载,但实施时需要综

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

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

相关文章

AI预警未来:山体滑坡与塌方事故的潜在发现者

在科技日新月异的今天,人工智能(AI)的应用已经渗透到了我们生活的各个领域。而在防灾减灾的领域中,AI技术的引入无疑为我们打开了一扇新的大门。以梅大高速大埔往福建方向K11900m附近发生的路面塌方灾害为例,我们不禁思…

C++ | Leetcode C++题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m matrix.size(), n matrix[0].size();int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 l…

UART、TIMER

UART简介&#xff08;通用异步收发器&#xff0c;通常称串口&#xff09; UART&#xff0c;是一种串行、异步、全双工的通信协议&#xff0c;在嵌入式领域应用的非常广泛。 UART作为异步串行通信协议的一种&#xff0c;工作原理是将传输数据的每个二进制位一位接一位地传输。…

五一 大项目

Docker 中的 Nginx 服务为什么要启用 HTTPS 一安装容器 1 安装docker-20.10.17 2 安装所需的依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm23 添加Docker官方仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos…

言出身随!人情世故:利益交换与人脉的重要性——早读(逆天打工人爬取热门微信文章解读)

巴黎输了&#xff0c;看了比赛还得加班 引言Python 代码第一篇 洞见 认知越高的人&#xff0c;越懂得感恩第二篇 冯站长之家 2024年5月8日&#xff08;周三&#xff09;三分钟新闻早餐结尾 智慧赋予我决策的明灯 勇气则是我行动的盾牌 在细雨中骑行 是我以智慧选择的道路 用勇气…

富唯智能复合机器人:CNC铝块上下料安全新标准

在CNC铝块加工过程中&#xff0c;上下料环节的安全问题一直是企业关注的焦点。富唯智能复合机器人的应用&#xff0c;为这一环节树立了新的安全标准。 传统的上下料方式往往依赖于人工操作&#xff0c;存在着较大的安全隐患。而富唯智能复合机器人采用先进的视觉识别技术和精准…

前端如何设置div可滚动,且设置滚动条颜色

在前端中&#xff0c;设置 div 为可滚动并通过 CSS 自定义滚动条的颜色并不是所有浏览器都直接支持的功能&#xff0c;因为滚动条的样式在很大程度上取决于操作系统和浏览器的默认样式。然而&#xff0c;你可以使用某些 CSS 属性来尝试自定义滚动条的外观&#xff0c;这些属性在…

一分钟教你学浪app视频怎么缓存

你是否在学浪app上苦苦寻找如何缓存视频的方法&#xff1f;你是否想快速、轻松地观看自己喜欢的视频内容&#xff1f;那么&#xff0c;让我们一起探索一分钟教你如何缓存学浪app视频的技巧吧&#xff01; 学浪下载工具我已经打包好了&#xff0c;有需要的自己下载一下 学浪下…

OpenAI的搜索引擎要来了!

最近的报道和业界泄露信息显示&#xff0c;OpenAI正秘密研发一款新的搜索引擎&#xff0c;可能叫SearchGPT或Sonic&#xff0c;目标是挑战Google的搜索霸权。预计这款搜索引擎可能在5月9日即将到来的活动中正式亮相。 SearchGPT的蛛丝马迹 尽管OpenAI对SearchGPT尚未表态&…

如何在Hostease的Linux虚拟主机上永久移除WordPress网站

最近有遇到客户咨询如何移除Linux虚拟主机上的WordPress网站的&#xff0c; 因为原先的站点长时间不更新&#xff0c;被恶意篡改&#xff0c;跳转到了一个博彩网站上&#xff0c;本身网站也比较旧了&#xff0c;客户也不准备修复&#xff0c;准备重新建站。但是又怕移除不干净&…

合并两个有序数组题目讲解

一&#xff1a;题目 非递减顺序可以理解为&#xff1a;不完全递增顺序&#xff0c;它不是完全的递增&#xff0c;会存在前后相等的情况&#xff0c;比如 [1&#xff0c;2&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;6] &#xff0c;这就是非递减顺序。 二&#xff1…

3. 分布式链路追踪的链路日志设计

前言 分布式链路追踪的客户端实现中&#xff0c;我们会通过各种手段和规则得到一个又一个的Span&#xff0c;得到这些Span后&#xff0c;需要在分布式链路追踪的服务端这边汇总这些Span并拼接出一条请求链路&#xff0c;那么这里就存在一个问题&#xff0c;客户端得到的Span如…

vue脚手架和vite创建的项目的环境配置

开发环境文件 .env.development NODE_ENV"development" # // 开发接口域名 本地测试就用这个 # vue脚手架创建的 VUE_APP_MODE"开发环境" VUE_APP_API_URL http://19527 # vite创建的 # VITE_MODE"开发环境" # VITE_BASE_URL http://1920:9527…

【自动驾驶|毫米波雷达】初识毫米波雷达射频前端硬件

第一次更新&#xff1a;2024/5/4 目录 整体概述 混频器&#xff08;MIXER&#xff09; 低通滤波器&#xff08;LPF&#xff1a;Low-Pass filter&#xff09; 数模转换器&#xff08;ADC&#xff1a;Analog to Digital Converter&#xff09; 毫米波雷达功能框图 整体概述 完…

开源go实现的iot物联网新基建平台

软件介绍 Magistrala IoT平台是由Abstract Machines公司开发的创新基础设施解决方案&#xff0c;旨在帮助组织和开发者构建安全、可扩展和创新的物联网应用程序。曾经被称为Mainflux的平台&#xff0c;现在已经开源&#xff0c;并在国际物联网领域受到广泛关注。 功能描述 多协…

如何利用AI提高内容生产效率

一&#xff1a;简介 通过AI技术可以在内容生产过程中提升效率和质量&#xff0c;以下是一些方法和应用场景&#xff1a; 1. 自动化内容生成&#xff1a; 自然语言生成&#xff08;NLG&#xff09;&#xff1a;通过AI技术&#xff0c;可以自动生成文章、报告、产品描述等文…

原型模式类图与代码

现要求实现一个能够自动生成求职简历的程序&#xff0c;简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同&#xff0c;并尽量减少程序中的重复代码。 采用原型模式(Prototype)来实现上述要求&#xff0c;得到如图 7.25 所示的类图。 原…

如何完美解决Outlook大文件传送问题,提升办公协作效率?

在日常工作中&#xff0c;邮件是一种常用的通信方式&#xff0c;经常用来发送各类文件&#xff0c;比如报告和文档、合同和协议、财务报表、营销资料、设计文件等。但有时文件会比较大&#xff0c;因此Outlook大文件传送时&#xff0c;会遇到附件大小受限的情况。常用的解决发送…

Sqlmap的使用

Sqlmap URL 检测 sqlmap直接对单一的url探测&#xff0c;参数使用-u或--url payload&#xff1a;sqlmap -u "http://192.168.10.1/sqlilabs/sqli-labs-php7-master/Less-1/?id1" --banner 注意&#xff1a;如果进入这个页面要先登录那么就需要把cookie带上 sqlm…

【MsSQL】数据库基础 库的基本操作

目录 一&#xff0c;数据库基础 1&#xff0c;什么是数据库 2&#xff0c;主流的数据库 3&#xff0c;连接服务器 4&#xff0c;服务器&#xff0c;数据库&#xff0c;表关系 5&#xff0c;使用案例 二&#xff0c;库的操作 1&#xff0c;创建数据库 2&#xff0c;创建…