Contents

redis

Redis

Redis 特点

  • 开源数据库

  • 配置简单

  • 支持内存存储数据

  • 支持持久化存储数据

    datafile 数据文件 *.rdb

    aof(append only file)文件,日志文件

  • 支持多实例部署

  • 支持主从复制、集群

  • 支持事务transaction

  • 以key-value键值对的方式存储

  • value类型:string字符串、list列表、set集合、sorted_set有序集合、hash值

安装

docker

使用 bitnami镜像 https://hub.docker.com/r/bitnami/redis

services:
  redis:
    image: bitnami/redis:6.2
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - /data/redis:/data
    environment:
      - REDIS_PASSWORD=Password123

redis 命令解释

  • redis-server:启动redis服务
  • redis-cli:redis客户端工具
  • redis-benchmark:redis性能测试
  • redis-check-rdb:检测rdb文件
  • redis-check-aof:检测aof日志文件

Redis 操作

[root@redis01 ~]# redis-cli 

127.0.0.1:6379> set age 16
OK
127.0.0.1:6379> get age
"16"
127.0.0.1:6379> set name martin
OK
127.0.0.1:6379> get name
"martin"
127.0.0.1:6379> 
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> 

127.0.0.1:6379> set name martin
OK
127.0.0.1:6379> get name
"martin"
127.0.0.1:6379> mset name tom age 15 sex male
OK
127.0.0.1:6379> mget name age sex
1) "tom"
2) "15"
3) "male"
127.0.0.1:6379> 

127.0.0.1:6379> strlen name
(integer) 3
127.0.0.1:6379> 

		
127.0.0.1:6379> set count 1
OK
127.0.0.1:6379> incr count
(integer) 2
127.0.0.1:6379> incr count
(integer) 3
127.0.0.1:6379> incr count
(integer) 4
127.0.0.1:6379> get count
"4"
127.0.0.1:6379> decr count
(integer) 3
127.0.0.1:6379> get count
"3"
127.0.0.1:6379> 
		
		
127.0.0.1:6379> set count 1
OK
127.0.0.1:6379> incrby count 3
(integer) 4
127.0.0.1:6379> get count
"4"
127.0.0.1:6379> decrby count 2
(integer) 2
127.0.0.1:6379> get count
"2"
127.0.0.1:6379> 

密码连接redis

# 方法1
[root@redis01 ~]# redis-cli 
127.0.0.1:6379> 
127.0.0.1:6379> AUTH redhat
OK

# 方法2
[root@redis01 ~]# redis-cli -a redhat 
127.0.0.1:6379> set age 10
OK

Redis 事物

192.168.122.102:6379> set count 1
OK
192.168.122.102:6379> multi
OK
192.168.122.102:6379> incr count
QUEUED
192.168.122.102:6379> incr count
QUEUED
192.168.122.102:6379> exec
1) (integer) 2
2) (integer) 3
192.168.122.102:6379> 
192.168.122.102:6379> get count
"3"
192.168.122.102:6379> 
	



192.168.122.102:6379> set number 1
OK
192.168.122.102:6379> MULTI
OK
192.168.122.102:6379> incr number
QUEUED
192.168.122.102:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
192.168.122.102:6379> 
192.168.122.102:6379> 
192.168.122.102:6379> 
192.168.122.102:6379> get number
"1"
192.168.122.102:6379> 

Redis 别名

[root@redis01 ~]# grep "^rename" /usr/local/redis/conf/redis.conf 
rename-command set uplooking
[root@redis01 ~]# 


[root@redis01 ~]# redis-cli -a redhat 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> set age 10
(error) ERR unknown command 'set'
127.0.0.1:6379> 
127.0.0.1:6379> uplooking age 10
OK
127.0.0.1:6379> get age
"10"
127.0.0.1:6379> 

别名可以用于规避危险命令

rename-command FLUSHALL ""
rename-command FLUSHDB  ""
rename-command CONFIG   ""
rename-command KEYS     ""

如果想要保留命令,但是不能轻易使用,可以重命名命令来设定,设置随机字符代替:

rename-command FLUSHALL joYAPNXRPmcarcR4ZDgC81TbdkSmLAzRPmcarcR
rename-command FLUSHDB  qf69aZbLAX3cf3ednHM3SOlbpH71yEXLAX3cf3e
rename-command CONFIG   FRaqbC8wSA1XvpFVjCRGryWtIIZS2TRvpFVjCRG
rename-command KEYS     eIiGXix4A2DreBBsQwY6YHkidcDjoYA2DreBBsQ

Redis持久化存储与备份

RDB持久化

将Redis在内存中的数据定时dump到磁盘上,实际操作过程是fork一个子进程,先将数据写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储

AOF持久化

AOF持久化:将Redis的操作日志以文件追加的方式写入文件,只记录写、删除操作,查询操作不会记录(类似于MySQL的Binlog日志)

自动间隔性保存

因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令

用户可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令 举个例子,如果我们向服务器提供以下配置

# redis
save 900 1
save 300 10
save 60 10000

那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行 服务器在900秒之内,对数据库进行了至少1次修改

服务器在300秒之内,对数据库进行了至少10次修改

服务器在60秒之内,对数据库进行了至少10000次修改。

RDB持久化实现

# redis.conf
# 默认redis会开启RDB持久化
备份文件的名称
dbfilename dump.rdb

备份文件存放路径
dir /var/lib/redis   

Redis的SAVE命令和BGSAVE命令用于将当前数据库备份

127.0.0.1:6379> save  #数据量大的话cpu会爆炸
OK

127.0.0.1:6379> bgsave    #建议使用这个
Background saving started

SAVE和BGSAVE命令的区别在于:SAVE命令是阻塞主进程,save操作完成之后,主进程才开始工作,客户端可以连接;BGSAVE命令是fork一个专门save的子进程,此操作不会影响主进程

注:SAVE只是将当前的数据库备份,备份文件名默认为dump.rdb,可通过配置文件修改备份文件名 dbfilename xxx.rdb(发现一个问题:如果要对多个数据库进行备份,那么最终只能备份最后一个数据库,因为dump.rdb文件会相互覆盖)

恢复

将备份的RDB文件,cp到要恢复的redis指定目录,重启Redis即可自动读取持久化文件,自动恢复数据

  • 备份的RDB文件: 通过命令redis 127.0.0.1:6379> CONFIG GET dir查看执行SAVE命令之后,redis默认存放备份文件的目录;通过命令redis 127.0.0.1:6379> CONFIG GET dbfilename查看备份RDB文件的文件名称;
root@pa6:~# redis-cli
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/var/lib/redis"
127.0.0.1:6379> CONFIG GET dbfilename
1) "dbfilename"
2) "dump.rdb"

AOF持久化实现

备份过程分以下三个阶段
  • 命令传播: Redis将执行完的命令、命令参数等信息发送到AOF程序
  • 缓存追加: AOF程序将接收到的命令内容追加到服务器的AOF缓存中
  • 文件写入和保存: AOF缓存中的内容被写入到AOF文件末尾,如果满足AOF保存条件,写入的内容会真正保存到磁盘中
进行AOF备份
  • 首先开启AOF功能
#此选项为aof功能的开关,默认为“no”,通过“yes”来开启aof功能
appendonly yes  

#指定aof文件名称
appendfilename appendonly.aof

#备份文件存放路径(此参数同样适用于指定RDB备份文件存放路径)
dir /var/lib/redis

二者优缺点

RDB持久化

优点:

  • RDB方式备份,整个Redis数据库最终备份成一个文件,这对于文件备份而言是完美的(方便管理、还原、压缩、转储)
  • 对服务进程影响最小,唯一需要做的是fork出子进程,之后所有的持久化工作交由子进程处理
  • 相比于AOF机制,如果数据量比较大,RDB的启动效率会更高(记录的是源数据,而非数据操作)

缺点:

  • 数据的可用性得不到太大的保障,如果在定时持久化之前出现宕机现象,此前没来得及写入磁盘的数据都将丢失
  • 如果数据量较大,fork子进程的操作可能会使服务短暂停止(通常是几百毫秒)

AOF持久化

优点:

  • 拥有更高的数据可用性,数据持久化最完整
  • 日志文件采用append模式,即使在写入过程中出现宕机现象,也不会破坏日志文件之前已经存在的内容
  • 提供rewrite机制,当日志过大时,Redis以append模式不断将修改的日志写入老的磁盘文件,同时Redis还会创建一个新的文件用于记录此期间有哪些命令被执行

缺点:

  • 对于相同数量的数据,AOF文件通常大于RDB文件,RDB文件在恢复大数据集的速度比AOF恢复的更快(RDB省去了执行的步骤,直接导入源数据)

总结

RDB持久化,性能更好(所有操作均由子进程处理,主进程不进行任何IO操作),数据一致性一般。

AOF持久化,数据一致性更好,性能一般(记录操作日志,写入日志和执行日志恢复数据的时间都比RDB更长)。

Redis 恢复的机制

  • 如果只配置 AOF ,重启时加载 AOF 文件恢复数据;
  • 如果同时配置了 RDB 和 AOF ,启动是只加载 AOF 文件恢复数据;
  • 如果只配置 RDB,启动是将加载 dump 文件恢复数据。
#!/bin/bash
# 避免造成雪崩
set -e
# bak 目录
BACKUPDIR=/data/redis/backup
#PASSWD='redis密码'
#DATADIR=`/usr/local/bin/redis-cli -p 端口 -a "$PASSWD" config get dir|grep -Ev 'dir|grep'`
# 获取redis-cli 二进制文件
REDIS_CMD=$(which redis-cli)
DATADIR=`$REDIS_CMD  config get dir|grep -Ev 'dir|grep'`
DATE=`date +'%Y-%m-%d-%H-%M'`
BACKUPDIR_DATE=$BACKUPDIR_$DATE

if [ ! -d $BACKUPDIR ];then
        mkdir -p $BACKUPDIR \
        || echo "can't make dir !!!" \
        && exit 1
fi
#以日期分类
mkdir -p $BACKUPDIR/$BACKUPDIR_DATE
$REDIS_CMD  bgsave
sleep 3
cp -rf $DATADIR/* $BACKUPDIR/$BACKUPDIR_DATE

redis 集群

  • 高可用性:Redis集群可以在某个节点发生故障时,自动进行故障转移,保证服务的持续可用。

  • 负载均衡:Redis集群可以将客户端请求分发到不同的节点上,有效地分摊节点的压力,提高系统的整体性能。

  • 容灾恢复:通过主从复制或哨兵模式,Redis集群可以在主节点出现故障时,快速切换到从节点,实现业务的无缝切换。

  • 数据分片:在Cluster模式下,Redis集群可以将数据分散在不同的节点上,从而突破单节点内存限制,实现更大规模的数据存储。

  • 易于扩展:Redis集群可以根据业务需求和系统负载,动态地添加或移除节点,实现水平扩展。

模式:

  • 主从
  • 哨兵
  • cluster

主从复制

主从复制是Redis的一种基本集群模式,它通过将一个Redis节点(主节点)的数据复制到一个或多个其他Redis节点(从节点)来实现数据的冗余和备份。

主节点负责处理客户端的写操作,同时从节点会实时同步主节点的数据。客户端可以从从节点读取数据,实现读写分离,提高系统性能。

一个主节点可以有多个从节点,一个redis可以即是主又是从,类似树状结构

配置:

1)配置主节点:在主节点的redis.conf配置文件中,无需进行特殊配置,主节点默认监听所有客户端请求。

# 主节点默认端口号6379
port 6379

2)配置从节点:在从节点的redis.conf配置文件中,添加如下配置,指定主节点的地址和端口:

# 从节点设置端口号6380
port 6380

# replicaof 主节点IP 主节点端口
replicaof 127.0.0.1 6379

或者,通过Redis命令行在从节点上执行如下命令:

redis> replicaof 127.0.0.1 6379

3)验证主从复制:在主节点上执行写操作,然后在从节点上进行读操作,检查数据是否一致。

主从复制的优缺点

优点

  1. 配置简单,易于实现。
  2. 实现数据冗余,提高数据可靠性。
  3. 读写分离,提高系统性能。

缺点

  1. 主节点故障时,需要手动切换到从节点,故障恢复时间较长。
  2. 主节点承担所有写操作,可能成为性能瓶颈。
  3. 无法实现数据分片,受单节点内存限制。

主从复制场景应用

主从复制模式适用于以下场景:

  1. 数据备份和容灾恢复:通过从节点备份主节点的数据,实现数据冗余。
  2. 读写分离:将读操作分发到从节点,减轻主节点压力,提高系统性能。
  3. 在线升级和扩展:在不影响主节点的情况下,通过增加从节点来扩展系统的读取能力。

总结:主从复制模式适合数据备份、读写分离和在线升级等场景,但在主节点故障时需要手动切换,不能自动实现故障转移。如果对高可用性要求较高,可以考虑使用哨兵模式或Cluster模式。

哨兵模式

Sentinel

哨兵模式是在主从复制基础上加入了哨兵节点,实现了自动故障转移。哨兵节点是一种特殊的Redis节点,它会监控主节点和从节点的运行状态。当主节点发生故障时,哨兵节点会自动从从节点中选举出一个新的主节点,并通知其他从节点和客户端,实现故障转移。

哨兵模式配置和实现

  1. 配置主从复制:首先按照主从复制模式的配置方法,搭建一个主从复制集群(上面已经讲过)。

  2. 配置哨兵节点:在哨兵节点上创建一个新的哨兵配置文件(如:sentinel.conf),并添加如下配置:

    # sentinel节点端口号
    port 26379
    
    # sentinel monitor 被监控主节点名称 主节点IP 主节点端口 quorum
    sentinel monitor mymaster 127.0.0.1 6379 2
    
    # sentinel down-after-milliseconds 被监控主节点名称 毫秒数
    sentinel down-after-milliseconds mymaster 60000
    
    # sentinel failover-timeout 被监控主节点名称 毫秒数
    sentinel failover-timeout mymaster 180000
    

    其中,quorum是指触发故障转移所需的最小哨兵节点数。down-after-milliseconds表示主节点被判断为失效的时间。failover-timeout是故障转移超时时间。

    为什么只配置了sentinel监控主节点,没有配置监控从节点? 因为通过主节点,就可以找到从节点。

  3. 启动哨兵节点:使用如下命令启动哨兵节点:

    redis> redis-sentinel /path/to/sentinel.conf
    
  4. 验证哨兵模式:手动停止主节点,观察哨兵节点是否自动选举出新的主节点,并通知其他从节点和客户端。

哨兵模式的优缺点

优点

  1. 自动故障转移,提高系统的高可用性。
  2. 具有主从复制模式的所有优点,如数据冗余和读写分离。

缺点

  1. 配置和管理相对复杂。
  2. 依然无法实现数据分片,受单节点内存限制。

哨兵模式场景应用

哨兵模式适用于以下场景:

  1. 高可用性要求较高的场景:通过自动故障转移,确保服务的持续可用。
  2. 数据备份和容灾恢复:在主从复制的基础上,提供自动故障转移功能。

总结:哨兵模式在主从复制模式的基础上实现了自动故障转移,提高了系统的高可用性。然而,它仍然无法实现数据分片。如果需要实现数据分片和负载均衡,可以考虑使用Cluster模式。

Cluster模式

Cluster模式原理

Cluster模式是Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。在Cluster模式下,Redis将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为槽位。通过对数据的分片,Cluster模式可以突破单节点的内存限制,实现更大规模的数据存储。

数据分片与槽位

Redis Cluster将数据分为16384个槽位,每个节点负责管理一部分槽位。当客户端向Redis Cluster发送请求时,Cluster会根据键的哈希值将请求路由到相应的节点。具体来说,Redis Cluster使用CRC16算法计算键的哈希值,然后对16384取模,得到槽位编号。

Cluster模式配置和实现

  1. 配置Redis节点:为每个节点创建一个redis.conf配置文件,并添加如下配置:

    # cluster节点端口号
    port 7001
    
    # 开启集群模式
    cluster-enabled yes
    
    # 节点超时时间
    cluster-node-timeout 15000
    

像这样的配置,一共需要创建6个,我们做一个三主三从的集群。

  1. 启动Redis节点:使用如下命令启动6个节点:

    redis> redis-server redis_7001.conf
    
  2. 创建Redis Cluster:使用Redis命令行工具执行如下命令创建Cluster:

    redis> redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
    

    cluster-replicas 表示从节点的数量,1代表每个主节点都有一个从节点。

  3. 验证Cluster模式:向Cluster发送请求,观察请求是否正确路由到相应的节点。

Cluster模式的优缺点

优点

  1. 数据分片,实现大规模数据存储。
  2. 负载均衡,提高系统性能。
  3. 自动故障转移,提高高可用性。

缺点

  1. 配置和管理较复杂。
  2. 一些复杂的多键操作可能受到限制。

Cluster模式场景应用

Cluster模式适用于以下场景:

  1. 大规模数据存储:通过数据分片,突破单节点内存限制。
  2. 高性能要求场景:通过负载均衡,提高系统性能。
  3. 高可用性要求场景:通过自动故障转移,确保服务的持续可用。

总结:Cluster模式在提供高可用性的同时,实现了数据分片和负载均衡,适用于大规模数据存储和高性能要求的场景。然而,它的配置和管理相对复杂,且某些复杂的多键操作可能受到限制。

模式选择

  1. 主从复制模式:适用于数据备份和读写分离场景,配置简单,但在主节点故障时需要手动切换。
  2. 哨兵模式:在主从复制的基础上实现自动故障转移,提高高可用性,适用于高可用性要求较高的场景。
  3. Cluster模式:通过数据分片和负载均衡实现大规模数据存储和高性能,适用于大规模数据存储和高性能要求场景。

在实际应用中,可以根据系统的需求和特点选择合适的Redis集群模式,以实现高可用性、高性能和大规模数据存储