您的位置:首页 > 数据库 > Redis

Redis 高级技术点解析

2019-05-03 19:32 246 查看
版权声明:转载请注明 https://blog.csdn.net/twt936457991/article/details/89790555

Redis 属于非关系型数据库,也被称之为 NoSQL 数据库,主要以 Key-Value 形式存储数据,是目前用得较多的一种非关系型数据库。

Redis 主要有如下特点:

  1. 为纯内存数据库,操作速度非常快;
  2. 可以通过持久化(如 RDB、AOF)保证数据基本不丢失;
  3. 数据类型丰富,常用数据类型有字符串(String)、散列(Hash)、列表(List)、集合(Set)、有序集合(Sorted set)等;
  4. 功能丰富,支持发布订阅、Lua 脚本、事务、Pipeline(管道,类似于关系型数据库的批量操作);
  5. 为单线程;
  6. 实现高可用比较灵活(主从复制、哨兵模式、集群);
  7. 易实现可扩展。

Redis 所包涵的内容非常多,无法在本课中一一讲解,为了让大家更高效地了解 Redis,我将从以下几个方面来介绍:

  1. Redis 快的主要原因;
  2. Redis 主从复制过程;
  3. Redis 数据分片原理及集群搭建;
  4. Redis 与 Lua 整合

Redis 快的主要原因

从 Redis 官网,我们可以清楚看到,Redis 单机读速度可达每秒 11万笔每秒,而写速度可达每秒8.1万。Redis 有如此快的读写速度,究其原因主要有以下三方面。

首先,Redis 为纯内存数据库,其操作均基于内存数据,这是 Redis 读写速度快的第一个原因。

同时,Redis 自身的数据结构也比较简单,主要使用 Hash 结构。同时优化了一些特殊数据的存储(如压缩表),并对短数据进行了压缩存储等,这是它读写速度快的第二个原因。

此外,Redis 使用了 I/O 多路复用模型。该模型可以让单个线程高效地处理多个连接请求,尽量减少网络 I/O 的时间消耗,这是它读写速度快的第三个原因。

上面提到 I/O 多路复用模型,有些朋友可能对它还不太了解。“多路”指的是多个网络连接,而“复用”指的是复用同一个线程。该模型利用 select、poll、epoll 可以同时监察多个流的 I/O 事件。事件处理器空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,程序会轮询一遍所有的流(epoll 只轮询那些真正发出了事件的流),并依次处理已就绪的流,这种做法避免了大量无用操作。

I/O 多路复用模型如下图:

Redis 主从复制过程

生产环境中使用 Redis,保证其高可用至关重要。不管利用 Redis 的主从、哨兵、还是集群模式实现高可用,了解其主从复制实现原理是很有必要的。

Redis 2.8 之后版本对主从复制的实现较之前版本已有较大区别。接下来,我们就来了解下它们之前的区别。为了方便叙述,下面将2.8之前的版本称为“旧版本”,2.8(包括2.8)之后的版本称为“新版本”。

旧版本复制功能实现

Redis 的复制功能分为同步(Sync)和命令传播(Command Propagate)两个操作。

同步操作

同步操作的主要作用是保证主、从数据库状态一致,即当主服务器数据库中数据更新后,从服务器数据需在很短时间内也做到同步更新。

同步操作时,客户端首先手动向从服务器发送 SLAVEOF 命令(为当前从服务器指定 Master 节点),从服务器接收到命令后,则向主服务器发送 SYNC 命令,从而实现主、从服务器数据状态的一致。
下面是 SYNC 命令执行的主要步骤:

  1. 从服务器向主服务器发送 SYNC 命令;
  2. 主服务器接收到 SYNC 命令请求后,执行 BGSAVE 命令生成 RDB 文件,同时开启一个缓冲区对从现在开始执行的所有写操作进行备份;
  3. 主服务器执行 BGSAVE 命令后,立即将生成的 RDB 文件发送给从服务器,从服务器接收并载入此 RDB 文件,将自己的数据库状态同步为主服务器执行 BGSAVE 命令时的数据库状态;
  4. 最后,主服务器将备份在缓冲区内的所有写操作命令发送给从服务器,从服务器执行写操作命令保证主、从服务器数据库中数据一致。

执行 SYNC 命令过程如下图所示:

命令传播操作

同步操作执行完毕后,主、从服务器上数据库中的数据将达到一致状态,但该状态只是暂时的,当主服务器执行写操作命令时,主服务器的数据库数据被修改,从而导致主、从数据库数据不一致。为了让主、从服务器上数据库的数据再次达到一致性,此时必须执行“命令传播操作”。

为了便于大家理解这一过程,请看下面图示说明。
(1)状态一致的主、从服务器:
(2)主服务器执行 set key5 value 命令后,主、从服务器的状态就不一致了:

(3)为了使主、从服务器数据库状态再次达到一致状态,主服务器需要对从服务器执行命令传播操作,即主服务器将自己执行的写命令发送给从服务器执行,当从服务器执行相同写命令之后,主、从服务器数据库再次达到一致状态:

旧版复制功能缺陷

旧版复制功能实现可以分为初次复制和断线后重复制。

初次复制,即从服务器数据库当前没有数据,或者从服务器当前复制的主服务器和上一次复制的主服务器不同。

断线后重复制,表示处于命令传播阶段的主、从服务器因网络原因而中断了复制操作,从服务器通过自动重连与主服务器再次建立连接,并继续复制主服务器写操作,从而使主、从服务器数据库数据最终达到一致性状态。

对于初次复制而言,旧版复制功能能够很好的完成复制任务,但对于“断线后重复制”来说,该功能效率是非常低下的,主要因为旧版的“断线后重复制”每次都需要通过从服务器向主服务器发送 SYNC 命令而实现对主服务器数据进行全量复制,而全量复制是非常耗时的一个操作。

新版本复制功能实现

为了改善旧版断线后重复制的功能,新版本将 SYNC 命令升级为 PSYNC 命令,以实现复制时的同步操作。PSYNC 命令具有完整重同步(Full Resynchronization)和部分重同步(Partial Resynchronization)两种模式。

完整重同步功能与旧版的初次复制功能一样,都是通过让主服务器执行 BGSAVE 命令创建并发送 RDB 文件,同时向从服务器发送备份在缓冲区内的写操作命令来同步数据,最终使得主、从服务器数据库数据状态一致。

部分重同步则用于处理断线后重复复制的问题,当从服务器断线后重新与主服务器建立连接后,主服务器将主、从服务器断线期间执行的写操作命令发送给从服务器,从服务器接收并执行这些写操作命令就可以使主、从服务器数据库状态达到一致。因为部分重同步属于增量同步,因此和旧版断线后重复制相比效率有较大的改善。

主、从服务器执行部分重同步的通信过程如下:

Redis 数据分片原理及集群环境搭建

实际生产环境中,利用 Redis 做缓存、排行榜应用、消息中间件、计数器及分布式锁等功能时,我们通常通过搭建 Redis 集群方式,来保证 Redis 的高可用。

为了帮助大家在生产环境中更好使用 Redis,下面将分别介绍 Redis 集群分片概念及如何搭建 Redis 集群。

Redis 数据分片

Redis 集群的整个数据库被分为16384个槽(Slot),数据库中的每个键都属于16384个槽中的一个,集群中的每个 Master 节点可以处理0个或者16384个槽。将集群整个数据库的16384个槽按照某种规则分配给集群中所有 Master 处理的过程称为 Redis 数据分片。

Redis 数据分片完成,意味着为集群中各个 Master 节点分别指定了要具体处理的槽。此时如果客户端向 Master 节点发送数据库键相关命令时,接收命令的节点利用算法 CRC16(Key) & 16383(槽号是从0至16383)计算出命令要处理的数据库键属于哪个槽,并检查该槽是否指派给了自己,如果不是,便指引客户端将命令发送到正确的节点。整个命令执行过程如下图所示:

Redis 与 Lua 整合

Lua 是由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于1993年开发的一种轻量、小巧的脚本语言,用标准 C 语言编写,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Redis 在 2.6 版本中推出了脚本功能,允许开发者将 Lua 语言编写的脚本传到 Redis 中执行。使用 Lua 脚本的优点有如下几点:

  • 减少网络开销:本来需要多次请求的操作,可以一次请求完成,从而节约网络开销;
  • 原子操作:Redis 会将整个脚本作为一个整体执行,中间不会执行其它命令;
  • 复用:客户端发送的脚本会存储在 Redis 中,从而实现脚本的复用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐