第1章 消息模式:

1.1 redis发布消息有两种模式:

1.      队列模式

2.      发布订阅模式

a)        任务队列:就是传递消息的队列,与任务队列进行交互的实体有两类,一类是生产者,另一类是消费者,生产者将需要处理的任务放在任务队里中,而消费者不断的从任务独立中读入任务消息并执行

任务队列的好处:松耦合,生产者和消费者只需按照约定的任务描述格式,进行编写代码

易于扩展,多消费者模式下,消费者可以分布在多个不通过额服务器中,由此降低单台服务器的负载

1.2 Redis发布订阅:

• Subscriber:收音机,可以收到多个频道,并以队列方式显示

• Publisher:电台,可以往不同的FM频道中发消息

• Channel:不同频率的FM频道

pub/sub的机制来看,他更像是一个广播系统,多个sub可以订阅多个channel,多个pub可以往多个channel中发布消息

1.3 发布订阅模型:

一个pub,多个sub模型 : 主要应用为通知,公告

image.png

多个pub,一个sub模型:

可以将pub做成独立的http接口,个应用程序作为pubchannel中发送消息,sub端收到消息后执行相应的业务逻辑,比如写数据库,显示等,主要应用 : 排行榜,投票,计数

image.png

多个pub,多个sub模型:

就是可以向不同的channel中发送消息,由不同的sub接受,主要应用 : 群聊,聊天

1.1 实践发布订阅:

发布订阅命令:

命令

描述

PUBLISH channel   msg

将信息 message 发送到指定的频道 channel

SUBSCRIBE   channel [channel ...]

订阅频道,可以同时订阅多个频道

UNSUBSCRIBE [channel   ...]

取消订阅指定的频道如果不指定频道,则会取消订阅所有频道

PSUBSCRIBE   pattern [pattern ...]

订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news  it.blog  it.tweets 等等) news.* 匹配所有以 news. 开头的频道( news.it news.global.today 等等),诸如此类

PUNSUBSCRIBE   [pattern [pattern ...]]

退订指定的规则如果没有参数则会退订所有规则

PUBSUB   subcommand [argument [argument ...]]

查看订阅与发布系统状态

1.2 模拟发布订阅:

127.0.0.1:6381> SUBSCRIBE fm

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "fm"

3) (integer) 1

 

 

127.0.0.1:6381> PUBLISH fm hello

(integer) 1

 

 

1) "message"

2) "fm"

3) "hello"

image.png

1.1.1 消息队列系统对比:

客户端在执行订阅命令之后进入了订阅状态,只能接收 SUBSCRIBE PSUBSCRIBE UNSUBSCRIBE PUNSUBSCRIBE 四个命令。

开启的订阅客户端,无法收到该频道之前的消息,因为 Redis 不会对发布的消息进行持久化。

和很多专业的消息队列系统(例如KafkaRocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择。

第2章 Redis事务管理:

redis中的事务跟关系型数据库中的事务是一个相似的概念,但是有不同之处

关系型数据库事务执行失败后面的sql语句不在执行,redis中的一条命令执行失败,其余的命令照常执行,redis中开启一个事务使用multi,相当于begin,exec用来提交事务,discard用来取消队列

2.1 mysqlredis对比:


MySQL

Redis

开启

start transaction/begin

multi

语句

普通SQL

普通命令

失败

rollback 回滚

discard 取消(不叫回滚,是队列里面的命令不执行,队列里面的任务根本就没有执行。而不是执行了也可以撤回来)

成功

commit

exec

2.2 redis事务命令:

命令

描述

DISCARD

取消事务,放弃执行事务块内的所有命令。

EXEC

执行所有事务块内的命令。

MULTI

标记一个事务块的开始。

UNWATCH

取消 WATCH 命令对所有 key 的监视。

WATCH key [key   ...]

监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动

那么事务将被打断。

2.3 事务执行举例:

127.0.0.1:6381> multi

OK

127.0.0.1:6381> set jiang 7

QUEUED

127.0.0.1:6381> exec

1) (empty list or set)

2) OK

127.0.0.1:6381> get jiang

"7"

2.3.1 redis事务中的锁机制:

举例:我正在买票 Ticket -1 , money -100 

而票只有1如果在我multi之后,exec之前票被别人买了,即ticket变成0了。

我该如何观察这种情景,并不再提交:

悲观的想法:

世界充满危险,肯定有人和我抢 ticket上锁只有我能操作. [悲观锁]

乐观的想法:

没有那么人和我抢,因此,我只需要注意,有没有人更改ticket的值就可以了 [乐观锁]

Redis的事务中,启用的是乐观锁,只负责监测key没有被改动.

2.4 Redis服务管理命令:

命令

描述

BGREWRITEAOF

异步执行一个 AOFAppendOnly File 文件重写操作

BGSAVE

在后台异步保存当前数据库的数据到磁盘

CLIENT KILL   [ip:port] [ID client-id]

关闭客户端连接

CLIENT LIST

获取连接到服务器的客户端连接列表

CLIENT GETNAME

获取连接的名称

CLIENT PAUSE   timeout

在指定时间内终止运行来自客户端的命令

CLIENT SETNAME   connection-name

设置当前连接的名称

CLUSTER SLOTS

获取集群节点的映射数组

COMMAND

获取 Redis 命令详情数组

COMMAND COUNT

获取 Redis 命令总数

COMMAND GETKEYS

获取给定命令的所有键

TIME

返回当前服务器时间

COMMAND INFO   command-name [command-name ...]

获取指定 Redis 命令描述的数组

CONFIG GET   parameter

获取指定配置参数的值

CONFIG REWRITE

对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写

CONFIG SET   parameter value

修改 redis 配置参数,无需重启

CONFIG RESETSTAT

重置 INFO 命令中的某些统计数据

DBSIZE

返回当前数据库的 key 的数量

DEBUG OBJECT key

获取 key 的调试信息

DEBUG SEGFAULT

 Redis 服务崩溃

FLUSHALL

删除所有数据库的所有key

FLUSHDB

删除当前数据库的所有key

INFO [section]

获取 Redis 服务器的各种信息和统计数值

LASTSAVE

返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示

MONITOR

实时打印出 Redis 服务器接收到的命令,调试用

ROLE

返回主从实例所属的角色

SAVE

异步保存数据到硬盘

SHUTDOWN   [NOSAVE] [SAVE]

异步保存数据到硬盘,并关闭服务器

SLAVEOF host   port

将当前服务器转变为指定服务器的从属服务器(slave server)

SLOWLOG   subcommand [argument]

管理 redis 的慢日志

SYNC

用于复制功能(replication)的内部命令

 

第3章 Redis主从复制:

基于RDB持久化的功能来实现主从复制的功能

3.1 redis复制特性:

1.      使用异步复制

2.      一个主服务器可以有多个从服务器

3.      从服务器也可以有自己的从服务器

4.      复制功能不会阻塞主服务器

5.      可以通过复制功能来让主服务器免于执行持久化操作,由从服务器执行持久化操作即可

                 image.png

3.2 主从复制原理:

1.      从服务器向主服务器发送sync命令

2.      接到sync命令的主服务器会调用bgsave命令,创建一个RDB文件,并使用缓冲区记录接下来执行的所有命令

3.      当主服务器执行完bgsave命令时,它会向从服务器发送RDB文件,而从服务器则会接受并载入这个文件

4.      主服务器将缓冲区存储的所有写命令发送给从服务器

3.3 复制中的syncpsync:

Redis2.8版本之后,redis使用psync代替sync命令,psync比起sync最大的改进在于实现了部分重同步的特性,即在服务器断线重新连接的时候,只要条件允许,psync可以让主服务器指向从服务器同步断线期间确实的数据,而不用重新向从服务器同步整个数据库

3.4 复制一致性的问题:

image.png

在读写分离环境下,客户端向主服务器发送写命令 SET n 10086,主服务器在执行这个写命令之后,向客户端返回回复,并将这个写命令传播给从服务器。

接到回复的客户端继续向从服务器发送读命令 GET n ,并且因为网络状态的原因,客户端的 GET命令比主服务器传播的 SET 命令更快到达了从服务器。

因为从服务器键 n 的值还未被更新,所以客户端在从服务器读取到的将是一个错误(过期)的 n值。

3.4.1 复制安全性的提升:

主服务器只在有至少 N 个从服务器的情况下,才执行写操作从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。

不过, 因为 Redis 使用异步复制, 所以主服务器发送的写数据并不一定会被从服务器接收到, 因此, 数据丢失的可能性仍然是存在的。

3.4.2 通过以下两个参数保证数据的安全:

在主服务器可以通过这两个参数来控制安全性,这两个参数的值都满足的情况下,主服务器将不会执行写操作

min-slaves-to-write <number of slaves>      几个从

min-slaves-max-lag <number of seconds>      最大延时的lag

第4章 主从复制搭建过程:

4.1 准备实例的目录:

[root@gitlab data]# ll

total 0

drwxr-xr-x 2 root root  6 Apr 17 00:05 6380

drwxr-xr-x 2 root root  6 Apr 17 00:05 6381

drwxr-xr-x 2 root root  6 Apr 17 00:05 6382

4.2 配置文件内容:

除端口不同,其余都相同

port 6380

daemonize yes

pidfile /data/6380/redis.pid

loglevel notice

logfile "/data/6380/redis.log"

dbfilename dump.rdb

dir /data/6380

protected-mode no

4.3 启动实例:

for i in {0..2};do redis-server /data/638${i}/redis.conf ; done

4.4 主从环境说明:

主库为6380,从库为6381,6382

4.4.1 开启主从:

 [root@gitlab ~]# redis-cli -p 6381

127.0.0.1:6381> SLAVEOF 127.0.0.1 6380

OK

[root@gitlab ~]# redis-cli -p 6382

127.0.0.1:6382> SLAVEOF 127.0.0.1 6380

OK

4.4.2 主库查看状态:

127.0.0.1:6380> info replication

# Replication

role:master

connected_slaves:2

slave0:ip=127.0.0.1,port=6381,state=online,offset=85,lag=0

slave1:ip=127.0.0.1,port=6382,state=online,offset=85,lag=0

master_repl_offset:85

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2

repl_backlog_histlen:84

4.4.3 从库状态:

127.0.0.1:6381> info replication

# Replication

role:slave

master_host:127.0.0.1

master_port:6380

master_link_status:up

master_last_io_seconds_ago:4

master_sync_in_progress:0

slave_repl_offset:141

slave_priority:100

slave_read_only:1

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

127.0.0.1:6382> info replication

# Replication

role:slave

master_host:127.0.0.1

master_port:6380

master_link_status:up

master_last_io_seconds_ago:10

master_sync_in_progress:0

slave_repl_offset:169

slave_priority:100

slave_read_only:1

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

4.5 主从复制管理:

宕掉主库:

127.0.0.1:6380> shutdown

主从切换:

 slaveof no one