reids解析

redis简介

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

redis作为缓存,如何添加?

reids解析

数据库缓存

        执行的过程包括sql,组织查询结果resultSet

        根据sql可以创建缓存,存储已经查过的resultset,节省了

        资源的调度重组resultSet

持久层缓存

        减少从数据库获取的结果转化成对象的过程,缓存存在直接调用其中

        保存的对象结果;

业务层缓存

        减少调用层次

控制层缓存

        较少调用层次

问题:可不可以过多的使用缓存?

缓存是占用内存空间的,过多的缓存插入,容易造成数据的冗余

在内存不够时,清空逻辑会交叉导致数据失效

结论缓存引入的最终目的:

        1 减少数据库的访问压力

        2 减少网络传输

        3 减少封装层次

问题:如果在缓存服务器宕机后,无法进行数据恢复/没有解决数据重新加载的问题,会导致“雪崩”/“缓存击穿”

雪崩/缓存击穿

海量用户访问请求涌入,一旦缓存失效(宕机数据丢失);所有的访问

涌入数据库;数据库无法承受海量数据的查询,导致数据库服务器宕机;

重启数据库,请求查询没消失,数据库--宕机--重启循环,导致系统崩溃

 

解决雪崩

1 缓存用不宕机;启动集群,永远让集群中的一部分起作用

2 缓存技术必须可以恢复数据,持久化

redis分布式

分布式,nosql,可以持久化,内存,数据库

分布式:数据被划分

nosql:not only sequence query language

不仅仅支持关系型数据--结构化的数据

还支持非关系型数据--非结构化数据


要完成数据的分片存储,需要至少多个redis实例

启动多个redis实例

前面的单个redis节点实例的启动时默认配置

端口号6379

 

配置文件

/redis根目录/redis.conf

reids解析

配置文件的修改内容

p61 bind 用#注释掉

reids解析

p80 保护模式不启动

reids解析

p84 6379是默认端口(要启动其他的redis实例需要修改端口

reids解析

p105 当客户端空闲时间一小时,就会自动断开连接,0秒表示

不启用超时配置

reids解析

p128 daemonize 设置成yes让redis服务器启动有守护进程管理

(后台执行)

reids解析

p150 对应不同的redis实例,pid的文件名称需要和端口同名

reids解析

save 900(秒) 1(变动的数据条数)

当900以内,至少有1条数据变动,看是flush保存数据到文件

save 300 10

300秒以内至少10条数据变动,保存文件

save 60 10000

reids解析

启动第二和第三个redis实例

redis-server redis.conf(指定启动文件)

需要第二个实例的配置文件

需要第三个实例的配置文件

拷贝redis.conf,用redis6380.conf,redis6381.conf

reids解析

将拷贝的文件中只修改与端口有关内容

port 

reids解析

pid文件

reids解析

6381的略

reids解析

启动另外两个节点

#redis-server redis6380.conf

#redis-server redis6381.conf

#ps -ef|grep redis

reids解析

指定端口登录客户端redis-cli -p [端口号]

#redis-cli -p 6380

reids解析

#redis-cli -p 6381

reids解析

6380和6381会共享6379dump.db文件

所以不同的节点实例在同一个机器上运行时,可以修改dump.db

指定端口文件;

 

三个节点,怎么分布式保存数据?

数据来源:代码的逻辑执行

如何使用代码来操作redis执行分布式的数据存储过程?

引出了Jedis客户端


jedis

测试jedis控制redis的命令功能

需要导入jedis包

自定义分片

准备数据:

葵花宝典A,B,C三部分数据

将三部分数据分别存储到redis 6379 6380 6381

 

哈希取余

利用hash的散列特性,可以处理海量非结构化数据的散列分布的分片计算

代码

 

jedis分片

没有在分片时使用哈希取余,hash一致性

 

经过代码发现,一般的自定义分片逻辑计算无法做到散列

不散列无法均衡

 

jedis池


HASH一致性


作为散列算法

考虑哈西取余的问题

1 容易产生大规模的数据倾斜(散列必定倾斜)

hash一致性一定程度的解决了数据倾斜;

2 哈希取余算法,导致数据迁移量过大

reids解析

redis集群数量进行增加减少的时候,哈希取余算法中的n变化了

由于n的变化,数据命中变化量非常大,需要迁移的数据量非常大,

 

jedis中引入另外一种hash散列算法--hash一致性

1997麻省理工学生发明;引入一个2^32-1(43亿)整数环,

把节点使用ip+端口做哈希散列计算,得到43亿中一个值,投射到环中

将所有的数据ke y进行哈希散列计算,得到43亿中的一个

reids解析

node1,2,3个节点启动着redis

数据分别是key1,2,3,4

根据hash散列算法都投射到一个整数上

顺时针寻找最近节点的映射规则,将key值进行存放

key1,2存储在node1

key3存储在node2

key4存储在node3

当增加删除节点时,迁移量有何变化?

reids解析

增加node4,根据散列得到43亿中一个整数,投射到环上

根据顺时针寻找最近节点存储的原则,只需要迁移key4

而且可以判断,原节点数量越多,迁移量越小

 

节点删除,将node2删除,迁移key3

reids解析

解决数据平衡性

单独的使用节点的ip+端口做映射,毕竟节点数量是有限的

有可能在映射时的各自分布位置并不平均,导致数据偏移量非常大

reids解析

解决数据的平衡性引入虚拟节点

node1的ip是192.168.40.156

node2的ip是192.168.40.157

各自引入2个虚拟节点(虚拟节点的数量是非常大的)

node1-1=hash(192.168.40.156#1)

node1-2=hash(192.168.40.156#2)

node2-1=hash(192.168.40.157#1)

node2-2=hash(192.168.40.157#2)

每一个虚拟节点在哈希环上也会接收顺时针寻找最近节点的key们

通过增加节点数量(虚拟的),完成数据的映射平衡

凡是投影到node1-1,node1-2的key,都会中真实存储在node1中

所以虚拟节点越多平衡性越好

 

hash取余数据分片

reids解析

 主从复制+哨兵集群

当前redis结构可用性非常低,当其中某个节点宕机时,数据不可查

reids解析

解决不可用需要引入高可用的结构

引入三台机器,将主节点的数据全部复制

主从复制,数据备份

reids解析

当主节点宕机后,如果从节点能够顶替主节点接收请求,这种结构就

叫做高可用,分布式架构中,必不可少高可用特性

AP理论

C: consistency(一致性)

A: avalibility(可用性)

P: Partition(分区)-tolerence to partition(分区容忍度)

随着数据量存储增长需求,业务的多元化,分布式结构必不可少,CAP理论

是分布始终的公认基础理论之一

分区:一个分布式系统中,多个系统组成网络本来应该是互通的,但是可能因为

某种原因导致某两个或几个节点间的数据通信断开;导致整个系统被分割成了

几个数据区域;(分区是常态);

当分区出现时,数据的修改就需要考虑一致性;

一致性:数据在某个查看的时间点上保持整体一致

如果在修改数据时,对于查看数据的客户端要求数据一致,必须加锁,实现整体数据一致性

如果在数据修改时,对于查看数据的客户端不要求数据一致;不是数据一致性的体现

分区容忍度:如果对数据一致性要求高的话,分区容忍度高,一致性需要执行(加锁)

如果对数据一致性要求低,分区容忍度低

如果要求数据一致性高的(加锁),查看数据的人在一段时间内无法进行查看了

可用性:请求在一定时间段内都有回应(返回的数据)

分区容忍度高--数据一致性要求高--可用性降低

CP理论

分区容忍度低--数据一致性要求低--可用性高

AP理论

 

CAP中分区是常态,不可避免,只能满足剩下两个理论中的一条与分区理论共存

不可能达到三种同时共存;

 

分区导致一致性的要求,要求高导致可用性低,要求低导致可用性高;

 

主从结构:

redis可以提供主从复制的结构,

master-slave,redis提供的主从结构可以多级复制

reids解析

主节点的数据实时同步到从节点,当搭建完成测试主从数据是否一致

修改,新增,删除一致


哨兵模式

测试主从结构的高可用

把主节点kill掉,看看某一个从节点能否主动担任主节点的功能,并且挂接另

一个从节点继续完成主从复制;

在主节点6382中执行操作

观察从节点状态

发现主从角色并没有转变,高可用未启动

redis中引入哨兵模式

哨兵是redis启动的进程,一个哨兵进程可以挂载一个主从的结构,来管理当前主从的高可用,多个哨兵进程可以挂载多个主从结构,多个哨兵可以挂载一个主从

哨兵进程通过连接主从执行info命令,判断当前主从结构是否正常,当发现主节点宕机,将会启动内部逻辑,将从节点中的slave-priority数值较高的节点启动替换主节点,将其他的从节点挂接到新的主节点上完成高可用主从替换

reids解析

当哨兵集群启动后,整体的架构就是高可用的最终模式

 

哨兵-主从复制的集群最终模式

reids解析

redis集群

哨兵集群的缺点:

1横向扩展不方便;一旦扩展,无论代码结构多么操作简单,都需要修改

reids解析

reids解析

哨兵集群和普通分布式redis集群都支持横向扩展

扩展后需要对代码进行重新编辑--redis集群解决了在横向扩展后,

代码无需变动

散列分布式算法是hash一致性;无论多少的数据迁移,都会造成调用代码

逻辑在扩展集群和收缩集群式做数据迁移

hash一致性虽然使数据迁移量得到缩小,但是每当扩展集群结构时,

如何迁移数据?

迁移数据需要额外编写代码

重新计算key的映射,将新的映射关系确定后,将key-value存到

对应新的节点

--redis集群可以不需要代码的数据迁移,手动迁移也可以,而且比代码执行

效率和方便程度高非常多;

特点:

集群中无需引入哨兵,集群的技术默认管理主从高可用结构

集群中的每个节点(redis实例)都两两相通,达到数据的传递高效

从节点也是整个集群中两两相通的成员之一;

reids解析

引入了一个虚拟槽道的概念

hash一致性不一样,不在将数据投射到43亿环上

而是使用一个0-16383号的槽道概念来对应key的映射

reids解析


redis集群架构

reids解析

对于客户端,连接redis集群无需配置全部ip和端口

最少配置一个就可以,分布式不是代码维护而是

集群内部管理数据分布;

 

内部数据key-value的传递过程是根据一个

0-16383(16384)槽道

内部的数据重定向(data redirect)

reids解析

这样一个结构可以改变扩容和收缩时修改代码配置的问题;

第一个问题,根据学习redis集群的架构,在redis集群中可以解决

 

迁移工作为什么不需要在集群中使用代码完成?

在集群中所有的key真正映射关系和redis节点本身无关,只和槽道号有关,需要数据迁移时,不能直接对key-value对数据操作,而是将槽道进行重新分配(reshard)

集群中的所有数据将会根据重新计算的槽道管理内容进行重新转发保存(迁移的过程类似于修改数据加锁的过程,不能再迁移时进行数据操作)

reids解析

重新分配槽道后,所有对应当前迁移这些槽道号的key-value数据对都会根据槽道的重新分配进行转发存储

1 计算槽道号

2 管理槽道号变化

3 重新计算key哈希取模

 

redis集群中,可以调用迁移命令来reshard数据槽道号;所以无需代码客户端调用程序重新分配数据;

问题:

每一个节点如何知道我自己的管理槽道到底是哪些?

如果自己不管理,如何获取共享信息将数据转发?

 

每一个节点都维护2个信息,一个是16384位的位序列

16384bit的二进制

每个节点都维护一个16384个元素的数组

reids解析


要知道本节点维护的槽道号,只需要访问计算本节点中这个16384位的位序列二进制

 

在集群中所有节点共享一个16384个元素的数组

数组元素保存节点信息;集群中每个节点的数组信息一致

reids解析

reshard分片过程中,位序列和数组的变化

位序列先计算,变化,每一个变动槽道号的master节点的位序列;

例子;7001 400-500;然后将这101个槽道挪走了挪到7002

位序列变化 400-500节点从1编程0;数组信息 400-500的元素清空;

7002 接收400-500;然后位序列中的400-500位从0变成1;将共享数组的400-500元素赋值,自己的值

 

主从从复制,主宕从顶的特点;

 

主从复制;复制主节点的key-value数据

位序列为0

共享数组也存在从节点;

主从替换;7001主,7003从

位序列不一样,数据一样,数组一样;

7003顶替的过程;将数组进行分析,是7001的获取下标,计算位序列;根据位序列修改数组,将位序列是1的下标对应更新数组元素;数组同步复制;

 

数据的重新计算:

1 主从替换时,数据完全不用动

2 reshard过程完成后,所有key重新计算,根据转发逻辑,改转发的转发,改保留的保留