Redis技术
Redis简介
Redis 是一个 key-value 的 nosql 产品,存储的 value 类型更加丰富,包括 string(字符串), list(链表),set(集合),zset(有序集合),hash(哈希)。为了保证效率,数据存储在内存中,而且 redis 会周期性的将数据持久化到硬盘上中,同时由于 redis 支持的 value 类型众多,也被称为结构化 nosql 数据库。
国外网站:http://redis.io/
国内网站:http://www.redis.cn/
Nosql 简介
由于目前属于 web3.0 时代,nosql 产品现在非常的火热,常见的 nosql 产品有 redis,mongodb。
Nosql 产品有两个非常显著的特点:
- Nosql 一般不是严格的表结构(行和列的组成形成一个表)
- Nosql 产品的查询一般都不使用 sql 查询
列出了世界上所有的 nosql 数据库
Redis安装
Linux下的安装
这样启动 redis 服务,就是后台启动了如何查看 redis 服务是否启动成功?
- 使用 ps 命令
- 使用netstat命令
如何关闭redis 服务? 使用pkill命令
如何启动redis客户端?
Redis的数据类型
String类型
1、 设置value
2、 获取value
3、incr做自增操作,可以对某个key的value做加1的操作
4、decr做自减操作,可以对某一个key的value做减1的操作
5、incrby指定自增的数字
6、decrby指定自减的数字
7、keys命令,获取redis里所有的key
8、redis的key如何设计?
原先在 mysql 数据库里数据是存储在 t_user 表里的。
Id |
username |
age |
1 |
tom |
24 |
2 |
jie |
25 |
如果要把上面的数据存储到 redis 里,key 如何设计?
① mysql 里的表名为 key 的前缀(t_user)
② 把 mysql 的主键名称放在前缀的后面(t_user:id)
③ 对应记录的主键值作为 key 的第三部分(t_user:id:1)
④ 把 mysql 里的其他字段作为 key 的第四部分(t_user:id:1:username) 把上面的 mysql 里的数据保存在 redis 里:
从 redis 里取出数据:
Hash类型
1、hset 设置单个值
2、hget 获取值
3、hmset 设置多个值
4、hmget 或 hgetall 获取多个值
List类型
1、lpush 向链表的头部加入数据
2、rpush 向链表的尾部加入数据
3、lrange 获取链表里面的数据
4、lpop 弹出链表左侧的第一个数据
5、rpop 弹出链表右侧的第一个数据
Set类型
redis 里的 set 类型称为集合类型三个特点:
① 无序性
② 唯一性
③ 确定性
集合常见运算:
① 交集(A∩B):集合公共的部分
② 并集(A∪B):集合全部部分
③ 差集(A-B):在 A 集合出现,但是不能在 B 集合出现
1、sadd 向集合里添加元素
2、smembers 获取集合里的元素
3、srem 从集合里删除元素
4、spop 随机的弹出集合里的某一个元素
5、sinter 取出两个集合的交集
6、sunion 取出两个集合的并集
7、sdiff 取出在 A 集合中存在,但是在 B 集合不存在的元素(求差集)
Zset类型
redis 里的 zset 被称为有序集合,意味着有序集合里面的元素是排好序的, 也满足唯一性和确定性。
1、zadd 添加元素
2、zrange 获取元素
3、将权重信息也显示出来
Redis的安全问题
在操作redis 的时候,默认是不需要客户端提供认证信息,不需要使用密码, 即可对 redis 进行操作,本身是很危险的,所以有必要开启 redis 的安全认证。
1、修改 redis.conf 配置文件
2、重启 redis 服务,使其生效
3、成功登录客户端以后,使用 auth+密码
或者在登录的时候使用-a 密码的方式授权
Redis的持久化功能
简介
redis 为了本身数据的安全和完整性,会把内存中的数据,按照一定的方式同步到电脑的磁盘上,这个过程叫做持久化操作。下次再次启动 redis 服务的时候,会把磁盘上面保存的数据重新加载到内存里面。
常见的持久化操作有两种:
- 基于快照的方式
redis 会按照一定的周期,把内存里面的数据同步到磁盘文件里
- 基于日志文件的追加
rdis 会把对 redis 数据造成更改的命令记录到日志文件里面,再一次重启服务的时候,会执行日志文件里对 redis 的写操作,达到数据的还原。
基于快照的持久化
1、修改 redis.conf 配置文件,开启基于快照持久化的选项
save 900 1 的含义:如果在 900s 内,对 redis 的 key 进行过一次操作, 则会把内存里的数据同步到磁盘文件里
save 300 10 的含义:如果在 300s 内,对 redis 的 key 进行过十次操作, 则会把内存里的数据同步到磁盘文件里
save 60 10000 的含义:如果在 60s 内,对 redis 的 key 进行过一万次操作,则会把内存里的数据同步到磁盘文件里
持久化文件存放的位置:
2、重启测试
基于文件追加方式持久化
1、修改 redis.conf 配置文件,开启基于文件追加方式的持久化
备份文件的周期:
appendfsync always 含义:只要存在对 redis 数据更改的操作,都要记录到磁盘文件上。
appendfsync everysec 含义:每 1s 将对 redis 数据造成更改的操作,记录到磁盘文件上。
appendfsync no 含义:完全交给操作系统来完成,意思就是在操作系统不繁忙的时候,将对 redis 数据造成更改的操作,记录到磁盘文件上,这种方式不可靠。
2、重启测试
杀掉 redis 服务,模拟断电效果,然后重启 redis 服务,获取之前保存的数据,也可以获取到
Jedis
Jedis介绍
Redis 不仅可以使用命令来操作,现在基本上的主流语言都有客户端的支持, 比如 java,c,c++,php,node.js 等。
在官方网站里列了一些java的客户端,有jedis,jredis,redission,jdbc-redis,
官方推荐使用 jedis 和redission,在企业中最常用的就是 jedis
单实例redis
多实例redis
jedis操作string类型
jedis操作hash类型
jedis操作list类型
jedis操作set类型
jedis操作sortset类型
keys常用命令
Redis 集群模式
主从复制模式
简介
主从复制,是指一台 redis 服务器的数据,复制到其他的 redis 服务器上。前者称为主节点,后者称为从节点,数据的复制是单向的,只能从主节点到从节点。
原理
redis 的主从复制原理基于同步和命令传播。
- 同步:从服务器主动获取主服务器的数据,保持数据一致。具体实现是从服务器向主服务器主动发送 SYNC 命令,主服务器收到 SYNC 命令后,执行 BGSAVE 命令,生成 RDB 快照文件,然后将快照文件发送给从服务器。
- 命令传播:主服务器收到客户端修改数据命令后,数据发生变化,同时将命令缓存下来,然后将缓存下来修改数据的命令发送给从服务器,从服务器通过载入修改数据的命令,保持与主服务器数据一致。
- 为什么需要有同步和命令传播两种操作:如果只有同步操作,那么主服务器在执行 BGSAVE 命令生成 RDB 快照文件的这段时间里收到的客户端修改数据的命令将只会在主服务器上生效,不会发送给从服务器,那么此时主从服务器数据不一致了,所以需要有命令传播这个操作,来弥补这个缺陷。
优缺点
- 优点:①实现了读写分离,提高可用性,解决了单机故障②主从复制期间,master 和 slave 是非阻塞方式,仍然可用。
- 缺点:① master 宕机期间,需要手工切换主机,同时会有部分数据不会同步到从服务器,造成数据不一致。② salve 宕机后,多个 slave 恢复后,大量的 SYNC 同步会造成 master IO 压力倍增。③在线扩容复杂
Sentinel 模式
简介
一个或多个 sentinel 实例组成的 sentinel 系统可以监视任意多个主服务器,以及这些主服务器所属的从服务器,并在主服务器下线后,可以自动切换从服务器为主服务器。
原理
哨兵集群中每个节点都会启动三个定时任务。
- 第一个定时任务:每个sentinel节点每隔1秒向所有的master、slave和别的sentinel节点发送一个PING命令,作用:心跳检测。
- 第二个定时任务:每个sentinel节点每隔2秒都会向master的__sentinel__:hello这个channel中发送自己掌握的集群信息和自己的一些信息(比如host,ip,run id),这个是利用redis的pub/sub功能,每个sentinel节点都会订阅这个channel,也就是说,每个sentinel节点都可以知道别的sentinel节点掌握的集群信息,作用:信息交换,了解别的sentinel的信息和他们对于主节点的判断。
- 第三个定时任务:每个sentinel节点每隔10秒都会向master和slave发送INFO命令,作用:发现最新的集群结构。
优缺点
- 优点:①哨兵模式基于主从复制,具备主从复制的优点②哨兵模式具备主从切换和故障转移,提高了更高的可用性
- 缺点:①较难支持在线扩容,在线扩容复杂
Cluster 模式
简介
Redis集群是一个由多个主从节点群组成的分布式服务集群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。redis集群的运用主要是针对海量数据+高并发+高可用的场景。
原理
redis 数据分片使用的是hash slot, redis集群有16384个哈希槽,每个Key通过CRC16校验后对16384取模来决定放置哪一个槽。
当存取redis key时候,redis会根据CRC16算法得到一个结果,然后把结果和16384求余,通过这个值去对应得节点获取数据。
这个时候,应用客户端实际上只需要连接其中任意一个节点即可,然后Redis Cluster 中每个节点都保存了其他节点得槽信息。这样当存取key计算完槽之后,通过保存槽信息从配置中获取节点信息,然后再去对应得节点获取数据。
优缺点
- 优点:①实现了分布式存储,节省了内存②在线扩容简单
- 缺点:①数据通过异步复制,不保证数据的强一致性
Redis 哨兵模式
哨兵的功能列表
1、监控
哨兵会不断的检查主节点和从节点是否在按预期工作。
2、通知
哨兵可以通过API通知系统管理员或其他的计算机程序,其中一个受监控的Redis实例出现了问题。
3、自动故障转移
如果主节点宕机了,哨兵可以启动自动故障转移过程,将从节点提升为主节点。
4、配置提供者
如果故障转移发生了,哨兵会告知客户端新的主节点地址。
搭建哨兵模式(基于redis7.0.4版本)
1、启动哨兵有两种方式
① sudo ./src/redis-sentinel sentinel.conf
② sudo ./src/redis-server sentinel.conf - -sentinel
哨兵这两种启动方式是完全一样的,配置文件都是需要强制指定的,如果没有指定或者配置文件不存在,哨兵都不会启动。哨兵的默认端口是26379,确保该端口不被占用且必须打开,否则永远不会执行故障转移。
2、配置哨兵模式
第一行配置用于告诉redis监视一个名为mymaster的主节点,它的地址是127.0.0.1,端口是6379,最后面的2是仲裁参数,简单解释说就是如果有5个哨兵,有2个哨兵同时同意主节点挂了,而且2个哨兵中的一个获得其他三个哨兵的授权,才会启动故障转移过程。
第二行配置的意思是主节点主观下线时长为60000毫秒,就是说其中一个哨兵每秒都会ping一下主节点(心跳检测),如果超过60秒没有收到回复,则认为该主节点主观下线了,为了确保主节点是否真的下线了,它会同样监视这个主服务器的其他哨兵实例,是否也认为该主节点已经下线了,如果有2个或2个以上哨兵都认为主节点下线了,则会进行故障转移。
第三行配置的意思是如果主节点降为从节点超过180s,或者从节点向新的主节点发起复制操作的时间(不包括复制数据的时间)超过180s,都会导致故障转移失败。如果超时,下一次超时时间会变为原来的2倍。
第四行配置的意思是规定了每次向新的主节点发起复制操作的从节点个数,默认是从节点一个一个复制,如果值为3,则是3个从节点一起复制,值越大,从节点完成复制的时间越快,但是对主节点的网络负载,硬盘负载造成的压力也是越大的,应根据实际情况设置。
3、哨兵部署
第一种部署方式:只部署两个哨兵在不同的服务器上,这两台服务器是可以互相通信的。
仲裁参数是1
第一种可能发生的情况:如果M1宕机了,由于两个哨兵可以就故障达成一致(根据配置该故障转移的条件是至少有一个哨兵不可访问到主节点,然后会在其中一个哨兵节点上启动故障转移),R1就会被提升为主节点[M1]。
第二种可能发生的情况:如果S1也宕机了,那么哨兵就只剩S2了,无法授权故障转移,那么该系统将变得不可用。
第三种可能发生的情况:如果M1是暂时性故障,此时从节点已经提升为主节点了,但是之前的主节点也恢复正常了,那么此时会出现两个主节点,这样客户端不知道该往哪个主节点写数据了。当从节点提升为主节点的时候,哨兵就会让原来的主节点执行slave of命令,和新的主节点重新进行全量同步,而在全量同步的最后阶段,原来的主节点会清空本地的数据,加载新的主节点发来的RDB文件,这样一来,原来的主节点在主从切换期间写的新数据就会被丢失。
脑裂:如果当前主节点出现暂时性失联,而不是真的发生了故障,此时监听的哨兵会自动启动主从切换机制,当这个原始的主节点从假故障中恢复后,又开始处理新的请求,但是哨兵已经选出了新的主节点,这样一来,旧的主节点和新的主节点就会同时存在,相当于一个人有两个大脑,不同的客户端就会往不同的主节点写数据。
解决脑裂:Redis提供了两个配置项来限制主节点的请求处理,min-replicas-to-write和min-replicas-max-lag。
min-replicas-to-write:这个配置项设置了主节点能进行数据同步的最少从节点数量。
min-replicas-max-lag:这个配置项设置了主从节点间进行数据复制时,从节点给主节点发送 ACK 消息的最大延迟(以秒为单位)。
我们可以把 min-replicas-to-write 和 min-replicas-max-lag 这两个配置项搭配起来使用,分别给它们设置一定的阈值,假设为 N 和 T。这两个配置项组合后的要求是,主节点连接的从节点中至少有 N 个从节点,和主节点进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主节点就不会再接收客户端的请求了。
即使原主节点是假故障,它在假故障期间也无法响应哨兵心跳,也不能和从节点进行同步,自然也就无法和从节点进行 ACK 确认了。这样一来,min-replicas-to-write 和 min-replicas-max-lag 的组合要求就无法得到满足,原主节点就会被限制接收客户端请求,客户端也就不能在原主节点中写入新数据了。
第二种部署方式:部署三个哨兵在不同的服务器上,这三台服务器是可以互相通信的。
仲裁参数是2
第一种可能发生的情况:如果M1所在的服务器与其他两台服务器发生网络中断,S2和S3就故障达成一致,选举R2为新的主节点,但是跟M1在同一网络里的C1,还会一直往旧的M1上写入数据,这样也就发生了脑裂现象,会丢失数据。
当网络故障修复后,哨兵会通知客户端新的主节点地址,C1就会往M2上开始写入数据。
第二种可能发生的情况:如果R2和R3都宕机了,那么M1也不能接收客户端的写入请求了。
4、实际操作
启动顺序:先启动 master 再启动slave 最后启动sentinel
总共有三台虚拟机ubuntu1(ip:10.211.55.4)、ubuntu2(ip:10.211.55.5)、ubuntu3(ip:10.211.55.6)
1、将主节点设置在ubuntu1上,先在ubuntu1上启动redis
2、在ubuntu2上启动redis
3、在ubuntu3上启动redis
4、启动三台虚拟机上的哨兵
5、向sentinel询问master的状态
num-slaves:说明该哨兵已经检测到有2个副本了
num-other-sentinels:说明该哨兵已经检测到有2个哨兵
6、测试故障转移
①查看此时的主节点地址
②杀死现在的主节点
③查看现在的主节点是否发生故障迁移
可以看到此时主节点到了ubuntu3上了