首页 > 编程知识 正文

redis cluster原理,redis集群三种方式

时间:2023-05-03 07:24:35 阅读:159147 作者:4981

基础概念

Redis用开源ANSI C语言编写,是一种支持网络、基于内存的可持续日志型Key-Value数据库

支持更多类型的value存储,包括字符串、列表、集、集、有序集、散列和cjdxt。 这些数据类型都支持推式/pop、add/remove、交集和差集以及更丰富的操作,所有这些操作都是原子的。 在此基础上,redis支持各种方式的排序。 与memcached一样,为了确保效率,所有数据都将缓存在内存中。 不同之处在于,redis会定期将更新的数据写入磁盘,或将更改操作写入添加的日志文件。 在此基础上实现了主从同步,以保证数据的备份。

设计思想

从设计到源代码,Redis都尽量精简,其中使用的原理也很简单。

Redis非常细致地考虑了数据的压缩、存储器碎片的减少等问题

Redis本质上是一种数据结构服务器(data structures server ),内置了基于hash的词典,因此没有类似MySQL的索引机制,可以高效地实现许多现成的数据结构

Redis采用单线程设计的优点是大大简化了数据结构和算法的实现。 相反,Redis通过异步IO和pipelining等机制实现了高速并发访问。

Redis使用dict的基础数据结构,解决了算法中的检索问题,缩短了响应时间

系统结构

网络模型

Redis是一个典型的基于Reactor的事件驱动模型,是一个高效的单进程单线程框架,总体上分为三个同步模块:接受请求的处理器、应答处理器和应答处理器

Redis集成了libevent/epoll/kqueue/select等多种事件管理机制,可以根据操作系统版本自由选择合适的管理机制。 其中libevent是最佳的选择机制。

Redis的网络模型具有所有事件驱动模型的优点,高效低功耗。 但是,如果面临费时的操作,则无法以同样的方式处理请求,在处理事件之前无法做出响应。 例如,如果删除redis中的所有密钥-值,则操作时间会变长,并且无法响应操作中的所有请求。 因此,了解网络模型有助于企业避免短要求,减少费时要求,尽可能多的简单费时要求发挥异步模型的最大威力。 事实上,这在Redis的设计中也多次出现

数据类型

Redis支持五种数据类型:字符串(字符串)、散列(cjdxt )、列表(list )、set (set )集合)和set (sorted set )有序集合。

String是Redis最基本的数据类型,一个密钥最多可以存储512MB。 字符串类型是二进制安全性。 表示redis的string可以包含任何数据。 例如,对于jpg图像或序列化对象,一个key对应一个value。

Hash Redis hash是键值value )的对集合,是string类型的field和value的映射表,hash特别适合存储对象。 每个hash可以存储232 -1键值对(超过40亿)

List Redis List列表是一个简单的字符串列表,按插入顺序进行排序。 可以在列表的开头(左)或末尾(右)添加元素。 列表最多可包含232 - 1个元素) 4294967295,每个列表可包含40亿个以上。

Set Redis的Set是string型的无序集合。

因为集合是通过cjdxt表实现的,所以添加、删除、检索的复杂度都是o(1)。

根据集合中元素的唯一性,第二次插入的相同元素将被忽略。

集合中的最大成员数为232-1(4294967295 ),每个集合可以存储40亿以上的成员。

Sadd:命令将string元素添加到与key相对应的set集合中,并成功返回1。 如果元素已经在集合中返回0,则与key对应的set中没有返回错误。

Zset Redis zset与set一样,是一组字符串元素,不允许重复成员。

不同的是,每个元素都有一个双精度得分与之相关联。 redis根据分数按从小到大的顺序对集合中的成员进行排序。 zset是唯一的成员,但“分数”(score )可以重复。

模式映射

各功能模块的说明:

文件事件:处理文件事件(在多个客户端多路复用,接受来自他们的命令请求(读取事件) (将命令的执行结果返回到客户端) ) ) )。

Time Event:时间事件(更新统计信息、清理过期数据、同步附属节点、定期持久性等) )。

AOF:命令日志数据持久性

RDB :实际数据持久化

Lua环境: Lua脚本的执行环境。 为了使Rua环境适应Redis脚本功能的需要,Redis对Lua环境进行了各种更改,包括添加函数库、替换随机函数和保护全局变量

执行Command table (命令表)命令时,根据字符查找相应命令的实现函数。

Share Objects (

对象共享):主要存储常见的值:a.各种命令常见的返回值,例如返回值OK、 ERROR、WRONGTYPE等字符;b. 小于 redis.h/REDIS_SHARED_INTEGERS (默认1000)的所有整数。通过预分配的一些常见的值对象,并在多个数据结构 之间共享对象,程序避免了重复分配的麻烦。也就是说,这些常见的值在内存 中只有一份。

Databases:Redis数据库是真正存储数据的地方。当然,数据库本身也是存储在内存中的。 (结构图见1.2.3.2数据库内存数据结构图)

核心原理

Redis的单线程和高性能
Redis 单线程为什么还能这么快?
因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
Redis 单线程如何处理那么多的并发客户端连接?
Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
Nginx也是采用IO多路复用原理解决C10K问题

持久化
RDB快照(snapshot)
在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。
你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:

# save 60 1000

AOF(append-only file)
快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件
你可以通过修改配置文件来打开 AOF 功能:

# appendonly yes

从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。
这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
你可以配置 Redis 多久才将数据 fsync 到磁盘一次。
有三个选项:
每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

Redis 4.0 混合持久化
重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。AOF在重写(aof文件里可能有太多没用指令,所以aof会定期根据内存的最新数据生成aof文件)时将 rdb文件的内容和增量的 AOF 日志文件存在一起,AOF根据配置规则在后台自动重写,也可以人为执行命令bgrewriteaof重写AOF。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。 于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

开启混合持久化:

# aof-use-rdb-preamble yes

混合持久化aof文件结构

缓存淘汰策略
当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。
在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。
当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。
volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

此文为多文档集合转载,时代久远已经无法考据,有疑问请私聊

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。