type
status
date
slug
summary
tags
category
icon
password
Property
目录
Redis
服务器是一个事件驱动程序,服务器需要处理以下两类时间事件:- 文件事件(file event):
Redis
服务器通过嵌套字与客户端进行连接,文件事件就是服务器对嵌套字操作的抽象。服务器与客户端的通信会产生响应文件事件,服务器通过监听并处理这些事件来完成一系列网络通信操作;
- 时间事件(time event):
Redis
服务器中的一些操作需要在给定事件点执行,而时间事件就是服务器对这类定时操作的抽象;
文件事件
Redis
基于Reactor
模式开发了自己的网络事件处理器, 这个处理器被称为文件事件处理器(file event handler):- 文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
type
status
date
slug
summary
tags
category
icon
password
Property
目录
Redis
服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。通过使用由I/O
多路复用技术实现的文件事件处理器,Redis
服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信。对于每个服务器进行连接的客户端,服务器都为这些客户端建立了相应的
redis.h/redisClient
结构(客户端状态),这个结构保存了客户端当前的状态信息,以及执行相关功能时需要用到的数据结构。Redis
服务器状态结构的clients
属性是一个链表,这个链表保存了所有与服务器连接的客户端的状态结构,对客户端执行批量操作,或者查找某个指定的客户端,都可以通过遍历clients
链表来完成:type
status
date
slug
summary
tags
category
icon
password
Property
Redis
服务器负责与多个客户端建立网络连接,处理客户端发送的命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源管理来维持服务器自身的运转。Redis 命令请求的执行过程
一个命令请求从发送到获得回复的过程中, 客户端和服务器需要完成一系列操作。如果使用客户端执行命令:
SET KEY VALUE
从客户端发送
SET KEY VALUE
命令到获得回复 OK
期间, 客户端和服务器共需要执行以下操作:- 客户端向服务器发送命令请求
SET KEY VALUE
- 服务器接收并处理客户端发来的命令请求
SET KEY VALUE
, 在数据库中进行设置操作, 并产生命令回复OK
- 服务器将命令回复
OK
发送给客户端
type
status
date
slug
summary
tags
category
icon
password
Property
目录
AOF和RDB,这两个持久化技术保证了即使在服务器重启的情况下也不会丢失数据(或少量损失)。不过,由于数据都是存储在一台服务器上,如果出事就完犊子了:
- 如果服务器发生了宕机,由于数据恢复是需要点时间,那么这个期间是无法服务新的请求的;
- 如果这台服务器的硬盘出现了故障,可能数据就都丢失了。
要避免这种单点故障,最好的办法是将数据备份到其他服务器上,让这些服务器也可以对外提供服务,这样即使有一台服务器出现了故障,其他服务器依然可以继续提供服务。
这些服务器之间的数据如何保持一致性呢?数据的读写操作是否每台服务器都可以处理?
Redis
提供了主从复制模式,这个模式可以保证多台服务器的数据一致性,且主从服务器之间采用的是「读写分离」的方式。type
status
date
slug
summary
tags
category
icon
password
Property
目录
在 Redis 的主从架构中,由于主从模式是读写分离的,如果主节点(master)挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点(slave)进行数据同步了。
这时如果要恢复服务的话,需要人工介入,选择一个「从节点」切换为「主节点」,然后让其他从节点指向新的主节点,同时还需要通知上游那些连接
Redis
主节点的客户端,将其配置中的主节点 IP 地址更新为「新主节点」的 IP 地址。这样也不太“智能”了,要是有一个节点能监控「主节点」的状态,当发现主节点挂了 ,它自动将一个「从节点」切换为「主节点」的话,那么可以节省很多事情。Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。
Sentinel
是Redis
的高可用性解决方案:由一个或多个Sentinel
实例组成的Sentinel
系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
一个Sentinel系统监视服务器的例子
type
status
date
slug
summary
tags
category
icon
password
Property
目录
节点
一个
Redis
集群通常由多个节点(node)组成, 在刚开始的时候, 每个节点都是相互独立的, 它们都处于一个只包含自己的集群当中, 要组建一个真正可工作的集群, 必须将各个独立的节点连接起来, 构成一个包含多个节点的集群。连接各个节点的工作可以使用
CLUSTER MEET
命令来完成:向一个节点
node
发送 CLUSTER MEET
命令, 可以让node
节点与ip
和port
所指定的节点进行握手(handshake), 当握手成功时, node
节点就会将 ip
和 port
所指定的节点添加到node
节点当前所在的集群中。 假设现在有三个独立的节点
127.0.0.1:7000
、 127.0.0.1:7001
、 127.0.0.1:7002
, 首先使用客户端连上节点7000 , 通过发送CLUSTER NODE
命令可以看到, 集群目前只包含 7000 自己一个节点:type
status
date
slug
summary
tags
category
icon
password
Property
目录
频道订阅(SUBSCRIBE、PUBLISH)
通过执行
SUBSCRIBE
命令,客户端可以订阅一个或多个频道,从而成为这些频道的订阅者(subscriber):每当有其他客户端使用PUBLISH命令向被订阅的频道发送消息(message)时,频道的所有订阅者都会收到这条消息。假设A、B、C三个客户端都执行了命令
SUBSCRIBE "news.it"
,那么这三个客户端就是"news.it"
频道的订阅者:如果这时某个客户端执行命令
PUBLISH "news.it" "hello"
,向"news.it"
频道发送消息"hello"
,那么"news.it"
的三个订阅者都将收到这条消息:模式订阅(PSUBSCRIBE)
type
status
date
slug
summary
tags
category
icon
password
Property
Lua
是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。创建并修改 Lua 环境
为了在
Redis
服务器中执行Lua
脚本, Redis
在服务器内嵌了一个Lua
环境, 并对这个Lua
环境进行了一系列修改, 从而确保这个Lua
环境可以满足Redis
服务器的需要。Redis 服务器创建并修改 Lua 环境的整个过程由以下步骤组成:
- 创建一个基础的
Lua
环境, 之后的所有修改都是针对这个环境进行的。
服务器首先调用
Lua
的C API
函数lua_open
, 创建一个新的Lua
环境。lua_open
函数创建的只是一个基本的Lua
环境, 为了让这个Lua
环境可以满足Redis
的操作要求, 接下来服务器将对这个Lua
环境进行一系列修改。- 载入多个函数库到
Lua
环境里面, 让Lua
脚本可以使用这些函数库来进行数据操作。