redis 常识

Redis 管道技术

Redis 基于客户端-服务端模型以及请求/响应协议的TCP服务。客户端 发送查询请求 服务端,并监听Socket返回,通常以阻塞模式,等待服务端响应;

管道技术 在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。(原理 java 处理并发请求的是排队队列)

优势,显著提高了redis服务的性能

Jedis jiedis = new Jedis("localjost",6379);
//获取管道
Pipline pp = jedis.pipelined();
//以下是批量数据测试,批量插入hash
Map<String, Map<String,String>> datas = new HashMap<String,  Map<String,String>>();
		
		for (int i = 0; i < 100000; i++) {
			Map<String, String> data = new HashMap<String, String>();
			//二级key
			data.put("name", "zhangsan");
			data.put("age", "18");
			data.put("sex", "男");
			//一级key
			datas.put("key"+i, data);
		}
		//以下是批量插入
		Set<String> keys = datas.keySet();
		for (String key : keys) {
			pp.hmset(key, datas.get(key));
		}
		
		jedis.close();


Redis Cluster

更多redis Cluster概念

Redis 集群搭建有 zookeeperproxy,Redis 3.0 之后版本支持 Redis Cluster 集群
Redis Cluster :无中心结构,每个节点保存数据和整个集群的状态,每个节点和其他所有节点连接

1.jpgredis 常识_第1张图片

高性能

1 采用异步复制机制,向某个节点写入数据,无需等待其它节点的写数据响应

2 无中心代理节点,客户端直接重定向到拥有数据的节点

3 对于N个节点的 Cluster ,整体性能理论上相当于单个 Redis 的 n 倍

高可用

1 采用主从复制机制,Master节点失效时 Slave 节点自动提升为Master节点

高扩展性

1 支持 1000 个服务节点。随时可向 Cluster 中添加新节点,或者删除现有节点

结构特点

1 所有 Redis 节点彼此互联(Ping-Pong 机制),内部采用二进制协议优化传输速度和带宽

2 节点的 fail 是通过集群中超半数的节点检测失效时,才生效

3 客户端与Redis节点直连,客户端不需要连接集群中所有的节点,连接任意一个可用的节点即可

4 Redis Cluster 将所有的物理节点映射到 [0-16383] Slot(哈希槽,不一定是平均分配),Cluster负责维护

5 Redis 集群预分好 16384 个哈希槽,当需要 Redis 集群中放置一个 key-value时,根据 CRC16(key) mod 16384 的值,决定一个key放在哪个桶中

主要组件
键分布模型

键(keys)空间有 16384 个Slot。Redis Cluster 理论上支持 16384 个Master。推荐的节点数量最多为 1000个Master。每个Master节点处理 部分Slot。每个Slot 分配到唯一的Master节点,每个Master节点有多个Slave节点

键哈希标记

对于形如 {xxx}yyy 键 ,redis 只对花括号里面的键进行哈希,所以xxx相同的数据会被放到同一个Slot里面

Cluster 结点属性

结点ID:Cluster 中每个节点都有一个唯一的名称。这个名称由一个 160bits 的随机数的十六进制形式来表示,这个随机数在结点首次启动时产生。修改结点的IP地址无需修改结点的ID,Redis Cluster 使用 gossip 协议自动检测结点的IP和端口的变化。

Cluster 总线(Bus)

Redis Cluster 的节点之间通过 Cluster 总线进行相互通信。如果节点通过端口 6379 与客户端通信,那么节点同时还需要通过 16379(10000+6379)与其它节点通信。节点之间的通信使用 Cluster总线协议(gossip) 进行通信,这个协议是一种二进制通信协议。

Cluster拓扑

N个节点的 Redis Cluster 中,每个节点都与 Cluster 中的每个其它节点之间建立了一个连接。N个节点的Cluster中,每个节点有 N-1个连接。整个 Cluster 为 PING/PONG 机制建立了 N*(N-1)/2 个连接。

节点握手

Redis Cluster 中的节点A发送 MEET 消息通知另外一个节点B,让节点B把节点A当做 Cluster 中的一员。如果节点A认识节点B,节点B认识节点C,那么节点B可以发送包含节点C信息的 MEET 消息给节点A,从而节点A也认识节点C了,即节点A将与节点C建立连接。

这个机制确保了以下两个结论的成立:

Redis Cluster 能够在人工组建了一个初始网络后,最终能够自动完成全网连接拓扑的建立。
Redis Cluster 能够阻止一个 Cluster 的节点在改变IP和端口后错误的混入其它 Cluster。

重定向
MOVED重定向

Redis 客户端可以向 Cluster 中的任何一个节点,包括任何 Master 和任何 Slave 节点发起查询。如果这个查询只包括一个键,或者所有的键都在同一个 slot 中,那么这个节点将继续判断这个 slot 是否归自己负责。如果是归自己负责,就直接向客户端返回查询结果;如果不归自己负责,就根据本节点保存的 slot 到节点的映射关系,找到负责这个 slot 的节点,取得其IP和端口,然后向客户端发送一个重定向消息MOVED,这个消息包含了负责这个 slot 的节点的 IP 和 端口 以及这个键的 slot,此时客户端需要重新向负责该 slot,即负责该键的新节点发起查询。

基于 Redis Cluster 的重定向机制,客户端存在以下的优化途径来降低重定向的成本,主要思路是客户端尽可能提高节点的命中率,即尽可能确保发起查询的键所对应的 slot 在查询的节点中。

客户端可以自行维护一个slot到节点(IP+端口)的映射。每当收到重定向消息时,将消息中包含的 slot 和 IP 和端口加入到这个映射中。

另外一种方法是在客户端刚启动时,以及在收到重定向消息时,发出命令 cluster nodes 或者 cluster slots 命令,查询 Cluster 中的 slot 和 节点 的映射关系,并保存到客户端本地。

Cluster 在线重新配置(live reconfiguration)

Redis Cluster 支持在 Cluster 运行过程中动态的增加或删除节点。增加或删除节点的本质是 slot 在节点之间的重新分配,即将 slot 从由一个节点负责,修改为由另外一个节点负责。

新增节点:将现有节点负责的一部分 slots 分配给新增的节点,现有节点不再负责这部分 slots。

删除节点:将待删除节点负责的全部 slots 分配到其它存活的节点,待删除节点不再负责这部分 slots。

ASK 重定向

假设的场景:slot8 当前由节点A负责,但是正在迁移到节点B,即由节点B负责。

客户端连接到节点A。客户端查询某个位于 slot8 中的键,该键已经迁移节点B。此时节点A可以向客户端发送 ASKING 重定向消息,表示客户端本次需要重定向到节点B去查询,但是所有后续查询还是应该查询节点A,因为 slot8 中的其它键还在节点A中,所以此时不能直接发送 MOVED 重定向消息。客户端收到 ASKING 重定向消息时显然不应该立即据此更新其 slot 到节点的映射关系。

当迁移完成后,节点A应该向客户端发送 MOVED 重定向消息,表示 slot8 已经永久重定向到了节点B。

应用程序的 mset/mget 优化

由于 mset/mget 命令中含有多个不同的键,如果这些键分不到很多不同的 slots 中,就有可能会分布到不同的节点中,这会带来很大的问题。此时应该使用键哈希标记(key hash tags)方法来解决这个问题,即通过让这写键有相同的标记的方式使得这写键全部位于相同的 slots 中,从而位于相同的节点中。

故障容忍度
心跳和 gossip 消息

Redis Cluster 持续的交换 PING 和 PONG 数据包。这两种数据包的数据结构相同,都包含重要的配置信息,唯一的不同是消息类型字段。PING 和 PONG 数据包统称为心跳数据包。

每个节点在每一秒钟都向一定数量的其它节点发送 PING 消息,这些节点应该向发送 PING 的节点回复一个 PONG 消息。节点会尽可能确保拥有每个其它节点在 NOTE_TIMEOUT / 2 秒时间内的最新信息,否则会发送一个 PING 消息,以确定与该节点的连接是否正常。

假定一个 Cluster 有 301 个节点,NOTE_TIMEOUT 为60秒,那么每30秒每个节点至少发送300个PING,即每秒10个 PING, 整个 Cluster 每秒发送 10 x 301 = 3010 个 PING。这个数量级的流量不应该会造成网络负担。

故障检测

Redis Cluster 的故障检测用于检测一个 Master 节点何时变得不再有效,即不能提供服务,从而应该让 Slave 节点提升为 Master 节点。如果提升失败,则整个 Cluster 失效,不再接受客户端的服务请求。

当一个节点A向另外一个节点B发送了 PING 消息之后,经过 NODE_TIMEOUT 秒时间之后仍然没有收到 PONG 应答,则节点A认为节点B失效,节点A将为该节点B设置 PFAIL 标志。

NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT时间内,当 Cluster 中大多数节点认为节点B失效,即设置 PFAIL 标志时,这个 Cluster 认为节点B真的失效了,此时节点A将为节点B设置 FAIL标志,并向所有节点发送FAIL消息。

在一些特定情况下,拥有 FAIL标志的节点,也可以清除掉 FAIL 标志。

Redis Cluster 故障检测机制最终应该让所有节点都一致同意某个节点处于某个确定的状态。如果发生这样的情况少数节点确信某个节点为 FAIL,同时有少数节点确认某个节点为非FAIL,则 Redis Cluster 最终会处于一个确定的状态:

情况1:最终大多数节点认为该节点FAIL,该节点最终实际为FAIL
情况2:最终在 N x NODE_TIMEOUT 时间内,仍然只有少数节点将给节点标记为FAIL,此时最终会清除这个节点的FAIL标志。

故障切换
当前世代(current epoch)

当多个节点提供了有矛盾的信息时,需要一种机制来决定哪个信息是最新的信息。在 Redis Cluster 中使用世代(epoch)这个概念来解决这个问题,它是一个64位无符号整数,相当于 Redis Cluster 中的逻辑时钟。

每个节点在创建时的世代为 0。当一个节点收到一条消息时,会比较发送者的世代与自己的世代。如果发送者的世代较大,则使用发送者的世代作为自己的世代。最终,Cluster 中所有节点的世代都是相同的,即那个最大的世代。

这个世代就是当前世代。当前世代如何增加的问题,在后面会介绍。

配置世代(config epoch)

在 Slave 节点提升为 Master 节点的过程中,Slave 节点会创建一个配置世代,等于 Master 节点的当前世代,同时还要增大这个值。当所有节点同意了这个提升,即赢得 Slave 选举时,Slave 节点将配置世代作为自己的当前世代。最终会成为 Cluster 中所有节点的当前世代。

Slave 选举和提升

当一个 Master 失效时,在符合以下情况时,将在该 Master 的所有 Slave 的范围内进行选举和提升:

1、该 Master 为 FAIL
  2、该 Master 失效前负责至少一个 slot。
  3、Master 和它的 Slave 之间的复制连接已经断开。

被选举者的范围:该 Master 的所有 Slaves。

选民的范围:所有的 Master。

投票规则:

1、在 NOTE_TIMEOUT * 2 时间之内,一个 Master 只能选中唯一一个 Slave,超出此时间可以再选其它Slave。目的是为了确保选举结果唯一。
  2、世代小于当前世代的投票将被忽略。目的的是为了确保该投票不是过期的之前的选举的投票。
  3、在符合1和2的前提下,投票赞成该 Slave 当选。

获胜规则:

某个 Slave 获得大多数的 Master 的投票。
  投票时间:

在选举开始之后的 2 * NODE_TIMEOUT 时间内投票有效。超时则选举自动取消。下一次选举至少在 4 * NOTE_TIMEOUT 时间之后才能举行。
  选举开始:

Slave 发出 FAILOVER_AUTH_REQUEST 消息。
  投票:

Master 发出 FAILOVER_AUTH_ACK 消息。
  在 Master 失效之后,Slave 按照以下公式计算结果决定何时开始发起选举请求:

DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds + SLAVE_RANK * 1000 milliseconds.

DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds + SLAVE_RANK * 1000 milliseconds.
1
  其中的固定值部分,确保 Master 的 FAIL 状态已经传播到每个节点;随机值部分则避免了多个 Slaves 在同一时刻发起选举请求。

SLAVE_RANK由 Slave 从 Master 那里复制了多少数据决定,复制最多的 Slave 的 RANK为 0,第 2 多的 RANK 为 1,依次类推。

基于投票规则,最早发起投票的 Slave,最有可能获胜。因此复制最多的 Slave 可能最先进行选举。

slots 配置传播

Redis Cluster 采用两种方式进行各个 Master 节点的 Slots 配置信息的传播。所谓 Slots 配置信息,即 Master 负责存储哪几个 Slots。

心跳消息

在 PING/PONG 消息中包含了所负责的 Slots 配置信息。

UPDATE 消息

当一个节点收到 PING/PONG 消息后,如果发现发送者的世代小于自己的世代,则向其发送 UPDATE 消息,来更新其有可能已经过时的 Slots 配置信息。如果发现发送者的世代大于自己的世代,则用消息中的 Slots 配置信息更新自己的 Slots 配置信息。

Resharding

Redis Cluster 的 Resharding 是指在 Cluster 内的节点之间转移 Slots 中的键数据,一个 Slot 之前由某个节点负责,在 Resharding 之后,可能由另外一个节点负责。

复制迁移

Redis Cluster 在节点失效时,可能进行自动的 Slave 节点重新配置,修改了 Cluster 中部分节点的 Master-Slave 复制关系,即复制迁移。

假定场景:

Cluster中有三个 Master 节点:A、B、C。A有1个 Slave 节点 A1,B有1个 Slave 节点B1,C有2个 Slave 节点C1和C2。A节点失效了,将A1节点提升为 Master 节点。

考虑不进行自动的 Slave 节点的复制迁移:

如果A失效了,则会将唯一的 Slave 节点A1提升为 Master 节点,但是它没有 Slave 节点。这时如果A1节点又失效了,则原来A节点负责的 Slots 将失效,导致整个 cluster 不能正常工作。

考虑进行自动的slave节点的复制迁移:

如果A节点失效了,将唯一的 Slave 节点A1提升为 Master 节点,由于它没有 Slave 节点,此时发现C节点有2个 Slave 节点,将其中的C2节点重新配置为A1节点的子节点。这时,Cluster 中每个 Master 节点至少有1个 Slave 节点。如果A1节点失效,可将C2节点提升为 Master。这样的结果是提高了整个 Cluster 的可用性。

Redis 持久化 AOF和RDB

RDB持久化(原理是将Reids在内存中的数据库记录定时 dump到磁盘上的RDB持久化),体积小

AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件)。体积大

更多介绍持久化

你可能感兴趣的:(redis)