Redis 概述
- Redis 的出现时间并不长,是 NoSQL 中的一种,基于键-值型的存储,在 2009 年第一次发布 Redis。
- Redis 全称(Remote Dictionary Server)远程字典服务器,而这个字典服务器从本质上来讲,主要是提供数据结构的远程存储功能的,可以理解为 Redis 是一个高级的 K-V 存储和数据结构存储,因为 Redis除了能够存储 K-V 这种简单的数据之外,还能够存储,列表、字典、hash 表、等对应的数据结构。
- Redis 支持主从模式,Redis 能够借助于 Sentinel 工具来监控主从节点,当主节点发生故障时,会自
- 己提升另外一个从节点成为新的主节点。 sentinel [ˈsentɪnl] 哨兵
- Redis 官网:https://redis.io
Redis 所支持的数据类型
- 支持存储的数据类型有、String(字符串,包含整数), List(列表), Hash(关联数组), Sets(集合), Sorted Sets(有序集合), Bitmaps(位图), HyperLoglog
- Redis 性能评估
- 100 万较小的键存储字符串,大概消耗 100M 内存
- 由于 Redis 是单线程,如果服务器主机上有多个 CPU,只有一个能够使用,但并不意味着 CPU 会成为瓶颈,因为 Redis 是一个比较简单的 K-V 数据存储,CPU 通常不会成为性能瓶颈
- 在常见的 linux 服务器上,500K(50 万)的并发,只需要一秒钟处理,如果主机硬件较好的情况下,每秒钟可以达到上百万的并发
- Redis 与 Memcache 对比
- Memcache 只能使用内存来缓存对象,若要持久化,需要第三方插件的支持。而 Redis 除了可以使用内存来缓存对像,还可以周期性的将数据保存到磁盘上,对数据进行永久存储。当服务器突然断电或死机后, redis 基于磁盘中的数据进行恢复。
- Redis 是单线程服务器,只有一个线程来响应所有的请求。Memcache 是多线程的
- Redis 支持更多的数据类型
-
试验环境
- 系统统一使用 CentOS 7.6 防火墙、iptables以及 SElinux 均为关闭状态
- 192.168.2.23 c7_2_23_redis1 Master
- 192.168.2.23 c7_2_24_redis2 Slave1
- 192.168.2.23 c7_2_25_redis3 Slave2
-
使用 Remi repository 源安装 redis
- 扩展:Remi repository 是什么源?
Remi repository 是包含最新版本 PHP 和 MySQL 包的 Linux 源,由 Remi 提供维护。有了这个源之后,使用 YUM 安装或更新 PHP、MySQL、phpMyAdmin 等服务器相关程序的时候就非常方便了。但与此同时,Remi 源也提供了目前最新版本的 Redis,可以通过该源使用 YUM 安装目前最新版本的 Redis。 - 在安装 Remi repository 源时,需要依赖 epel 源,因此先安装 epel 源
- 这里使用 aliyun 的源
- Remi repository 官网:http://rpms.remirepo.net/enterprise/
-
分别在3台服务器上安装 Remi repository 源
- yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
- 查看 源文件
- yum repolist all
- 使用 remi repository 源安装 Redis
yum --enablerepo=remi install -y redis - 注:/etc/yum.repos.d/remi.repo 源安装完成后,默认为disabled,使用--enablerepo=remi 选项指定使用 remi repository 源进行安装。
- 查看 Redis 版本
redis-cli --version
- 启动 Redis
- systemctl enable redis.service --now
- redis 默认端口为 6379
-
Redis 基本操作
- Redis 配置文件参数说明
- Redis 配置文件存放路径:/etc/redis.conf
vim /etc/redis.conf #配置文件中主要参数如下
改:69 bind 127.0.0.1
为:69 bind 0.0.0.0 #redis 监听的地址,默认监听在 127.0.0.1 地址上,改为 0.0.0.0 地址或192.168.2.23
以下内容,保持不变,大家可以了解一下,每个配置的含意:
protected-mode yes #参数是为了禁止外网访问 redis,如果启用了,则只能够通过 lookback ip(127.0.0.1)访问 Redis。
port 6379 #默认监听端口:6379。
tcp-backlog 511 #指定 tcp-backlog 的长度。backlog 是一个等待队列。当有大量请求需要redis 处理时,redist 有可能处理不过来,需要等待的请求队列会通过 backlog 来缓存。backlog 的数量决定了可以缓存的队列数。
unixsocket /tmp/redis.sock #指定使用 sock 文件通信及 sock 文件位置,如果服务端和客户都在同一台主机上,建议打开此项,基于 sock 方式通信可以直接在内存中交换,数据不用再经过 TCP/TP 协议栈进行封装、拆封。
unixsocketperm 700 #定义 sock 文件的访问权限。
timeout 0 #表示当客户端连接成功后,空闲(非活跃、或没有任何数据交互)多长时间则连接超时,0 表示不启用此功能。
tcp-keepalive 300 #定义是否启用 tcp-keepalive 功能。长链接功能。
daemonize no #如果需要在后台运行,把该项改为 yes。如果使用 redis 服务脚本启动,即使daemonize 为 no,也会运行为一个守护进程。
supervised no #定义是 upstart 还是 systemd 接管 redis 进程。默认无监督互动,不需要修改。
loglevel notice #定义日志级别。
logfile /var/log/redis/redis.log #定义日志文件。
databases 16 #定义 redis 默认有多少个 databases,但是在分布式中,只能使用一个。
# masterauth <master-password> #如果连接主数据库时需要密码验证,在这里指定密码。默认不启用。
# 限制同时连接的客户端数量。超过数量将不再接受新的请求并返回错误信息。
# maxclients 10000 #设置同时连接 redis 客户端的最大数量。
- 登录 Redis
- redis-cli
- 选项:
- -h <hostname> 指定主机 IP -p <port> 指定端口 socket 文件进行通信。
- redis-cli -h 127.0.0.1 #连接 redis,默认不启用密码认证。
- 127.0.0.1:6379> exit #退出连接。
- 或:
- redis-cli #使用 redis-cli 直接连接,默认连接是 127.0.0.1 IP。
- Redis 字符串(String)操作
键的命名规则遵循
1.可以使用 ASCII 字符
2.键的长度不要过长,键的长度越长则消耗的空间越多
3.在同一个库中(名称空间),键的名称不得重复,如果复制键的名称,实际上是修改键中的值
4.在不同的库中(名称空间),键的多种名称可以重复
5.键可以实现自动过期 - 设置键 system 的值为 centos
- 127.0.0.1:6379> set system centos
OK
127.0.0.1:6379> get system
"centos"
- 定义一个键 name 值为 zhangsan,并设置过期时间为 60 秒。
127.0.0.1:6379> set name zhangsan EX 60
- 开启 redis 用户认证服务
vim /etc/redis.conf
改:507 # requirepass foobared #启用此项,并指定密码即可。
为:507 requirepass 123456 #指定密码为 123456。
systemctl restart redis #重启服务。 - edis-cli
127.0.0.1:6379> get name
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> get system
"centos"
127.0.0.1:6379>
redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> get system
"centos"
127.0.0.1:6379>
配置 Redis 持久化
- redis 持久化概述
- Redis 工作时所有数据集都是存储于内存中的,如果 Redis 崩溃或断电导致所有数据丢失,所以 Redis提供了持久化功能来保证数据的可靠性
- Redis 持久化有两种实现方法:RDB 和 AOF
- RDB: 存储为二进制格式的数据文件,是默认启动的持久化机制;按事先定制的策略,周期性地将数据保存至磁盘。
- AOF:Append Only File 类似于 MySQL 的二进制日志,记录每一次 redis 的写操作命令,以顺序 IO 方式附加在指定文件的尾部,是使用追加方式实现的,这也叫做一种附加日志类型的持久化机制。
- 由于每一次的操作都记录,则会随着时间长而增大文件的容量,并且有些记录的命令是多余的。但是 redis 进程能够自动的去扫描这个对应的 AOF 文件,把其中一些冗余的操作给合并一个,以实现将来一次性把数据恢复。
- 总结:AOF 记录操作命令,RDB 是直接保存数据集的本身。
-
配置文件中的与 RDB 相关的参数
- vim /etc/redis.conf #默认参数就够用了。
- stop-writes-on-bgsave-error yes #在进行快照备份时,一旦发生错误的话是否停止。
- rdbcompression yes #RDB 文件是否使用压缩,压缩会消耗 CPU。
- rdbchecksum yes #是否对 RDB文件做校验码检测,此项定义在 redis 启动时加载 RDB文件是否对文件检查校验码,在 redis 生成 RDB 文件是会生成校验信息,在 redis 再次启动或装载 RDB 文件时,是否检测校验信息。如果检测的情况下会消耗时间,会导致 redis 启动时慢,但是能够判断 RDB 文件是否产生错误。
- dbfilename dump.rdb #定义 RDB 文件的名称。
- dir /var/lib/redis #定义 RDB 文件存放的目录路径。
-
注意:持久化本身不能取代备份;还应该制定备份策略,对 redis 数据库定期进行备份。
- vim /var/lib/redis/dump.rdb #可查看到数据已经保存在磁盘上
-
搭建 Redis 主从复制架构
- 主从复制的工作过程
Redis 的主从复制是自动进行的,并不需要用户的介入,slave 端会自动连接 master 并进行数据同步。如果同步连接时 slave 端短暂的与 master 端断开了连接,那连接恢复后 slave 端会与 master 端进行一次同步。从而保证数据一致。 - Redis 主从同步数据流程如下图:
- master 不需要特别配置保证能正常运行即可
- 只需要在 slave1 和 2 上配置
- vim /etc/redis.conf
replicaof 192.168.2.23 6379 master 的 IP 以及端口
masterauth 123456 master 密码,如果没有密码可以不设置
requirepass 123456
- 登录 master 2.23 查看主从复制状态
- info replication
- redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:master 角色 master
connected_slaves:2 slave 数量 2 个
slave0:ip=192.168.2.24,port=6379,state=online,offset=0,lag=0 slave 1 信息
slave1:ip=192.168.2.25,port=6379,state=online,offset=0,lag=0 slave 2 信息
master_failover_state:no-failover
master_replid:9f270ccf6277aa3b5652f0216d1953f4dcd0ec47
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
127.0.0.1:6379>
- redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:slave 角色 slave
master_host:192.168.2.23 mster IP地址
master_port:6379 master 端口
master_link_status:up 状态 UP 为已经同步
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:406
slave_priority:100
slave_read_only:1 成为从服务以后,1 表示该服务器为只读。
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:ac49e447d70bee8f57428b1d35391150e0dfba74
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:406
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:407
repl_backlog_histlen:0
127.0.0.1:6379>
-
测试
- 在 master 端 创建一个 user 键
- 在 slave 端 查看
- 可以查看到键值,说明主从数据同步成功。
-
查看 redis 从服务器上有关主从复制的高级配置参数
- /etc/redis.conf #保持默认参数就可以,不需要修改
#### SNAPSHOTTING #### #定义快照存储的策略,定义存到硬盘的持久化策略。
save <seconds> <changes> #使用 save 指令,并指定每隔多少秒,如果发生多大变化,进行存储。
save 900 1 #表示在 900 秒(15 分钟内),如果至少有 1 个键发生改变,则做一次快照(持久化)
save 300 10 #表示在 300 秒(5 分钟内),如果至少有 10 个键发生改变,则做一次快照(持久化)
save 60 10000 #表示在 60 秒(1 分钟内),如果至少有 10000 个键发生改变,则做一次快照(持久化)。
replica-serve-stale-data yes #当 slave 端在主从复制的过程中与 master 端断开了连接,此时有 2 种处理方法:一种是继续提供服务即使数据可能不是最新的,另一种是对请求返回一个错误信息,默认配置是继续提供服务。replica [ˈreplɪkə] 复制品 ; stale [steɪl] 不新鲜的
replica-read-only yes #redis 从只读。自 redis 2.6 版本开始,slave 端默认为 readonly
repl-diskless-sync no #默认不使用 diskless 同步方式 。
扩展:主从同步支持两种策略,即 disk 和 socket 方式(socket 方式尚不完善,还处于实验阶段)。
新的 slave 端和重连的 salve 端不允许去继续同步进程,这被称之为“完全同步”。 - 一个 RDB 文件从 master 端传到 slave 端,分为两种情况:
- 支持 disk:master 端将 RDB file 写到 disk,稍后再传送到 slave 端;
- 无磁盘 diskless:master 端直接将 RDB file 传到 slave socket,不需要与 disk 磁盘进行交互。
- 无磁盘 diskless 方式适合磁盘读写速度慢但网络带宽非常高的环境。
repl-diskless-sync-delay 5 #无磁盘 diskless 方式在进行数据传递之前会有一个时间的延迟,以便 slave 端能够进行到待传送的目标队列中,这个时间默认是 5 秒 。
repl-ping-replica-period 10 #slave 端向 server 端发送 pings 的时间区间设置,默认为10 秒
repl-timeout 60 #设置超时时间
repl-disable-tcp-nodelay no #是否启用 TCP_NODELAY,如果启用则会使用少量的 TCP包和带宽去进行数据传输到 slave 端,当然速度会比较慢;如果不启用则传输速度比较快,但是会占用比较多的带宽。
repl-backlog-size 1mb #设置 backlog 的大小,backlog 是一个缓冲区,在 slave 端失连时存放要同步到 slave 的数据,因此当一个 slave 要重连时,经常是不需要完全同步的,执行局部同步就足够了。backlog 设置的越大,slave 可以失连的时间就越长。
repl-backlog-ttl 3600 #如果一段时间后没有 slave 连接到 master,则 backlog size 的内存将会被释放。如果值为 0 则表示永远不释放这部份内存。 默认是 3600 秒
replica-priority 100 #slave 端的优先级设置,值是一个整数,数字越小表示优先级越高。当master 故障时将会按照优先级来选择 slave 端进行恢复,如果值设置为 0,则表示该 slave 永远不会被选择。
min-replicas-to-write 3
min-replicas-max-lag 10 #这两行的意思是,设置当一个 master 端的可用 slave 少于 N个,延迟时间大于 M 秒时,不接收写操作。
当 master 可用的从服务器少于 3 个或网络延迟时间大于 10 秒时,master 将拒绝接收用户的写请求
-
使用 Sentinel 实现 Redis 集群高可用部署
- redist 主从架构中,如果主服务器离线,那么所有写操作操作则无法执行。为了避免此情况发生,redis 引入了 sentinel(哨兵)机制,当 redis 主挂了,redis 从可以主动变成主。
- Sentinel 概述和工作过程
Sentinel 作用:检测 Master 状态,如果 Master 异常,则会进行 Master-Slave 切换,将其中一个 Slave 作为 Master,将之前的 Master 作为 Slave 。当 Master-Slave 切换后,master-redis.conf、slave-redis.conf 和 sentinel.conf 的内容都会发生改变,即 master-redis.conf 中会多一行 slaveof 的配置,sentinel.conf 的监控目标会随之调换 - Sentinel 工作方式
Sentinel 是 Redis 官方提供的一种高可用方案(除了 Sentinel,Redis Cluster 是另一种方案),它可以自动监控 Redis master/slave 的运行状态,如果发现 master 无法访问了,就会启动 failover 把其中一台可以访问的 slave 切换为 master。 - 支持 Sentinel 的 Redis 客户端(例如 Java 的 Jedis)会在连接 Redis 服务器的时候向 Sentinel 询问 master 的 ip,并且会在收到 master 切换的 pub/sub 事件后自动重新连接到新的 master。对调用Redis 客户端的业务系统来说,这些都是完全透明的。
- 下图是 redis sentinel 的部署和运行机制 :
- 扩展:redis 主观下线和客观下线
主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个 redis 服务器做出的下线判断。 Subjectively [səb'dʒektɪvlɪ] 主观地
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对 Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server 下线判断,然后开启 failover。 Objectively [əb'dʒektɪvlɪ] 客观地 -
使用 Sentinel 实现 Redis 集群高可用部署
- 修改 /etc/redis.conf
- 首先在 192.168.2.23 master 端
- 取消 密码认证
- protected-mode no #关闭 protected-mode,允许外网访问 redis 服务器。
- /etc/redis.conf
bind 0.0.0.0
protected-mode no
#requirepass 123456 - 完整的配置文件内容
- cat /etc/redis.conf
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
pidfile "/var/run/redis_6379.pid"
loglevel notice
logfile "/var/log/redis/redis.log"
databases 16
always-show-logo no
set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dump.rdb"
rdb-del-sync-files no
dir "/var/lib/redis"
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
maxclients 10000
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
lazyfree-lazy-user-flush no
oom-score-adj no
oom-score-adj-values 0 200 800
disable-thp yes
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4kb
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes
supervised systemd
save 3600 1
save 300 100
save 60 10000
user default on nopass ~* &* +@all
-
接着配置 sentinel1
vim /etc/redis-sentinel.conf
改: # protected-mode no
为: protected-mode no
port 26379 #默认,保持不变
改:daemonize no
为:daemonize yes
改:sentinel monitor mymaster 127.0.0.1 6379 2
为:sentinel monitor mymaster 192.168.2.23 6379 2
注:# sentinel monitor <master-name> <ip> <redis-port> <quorum> 每项含意如下:
<master-name>为集群名称,可以自定义,如果同时监控有多组 redis 集群时,<master-name>不能一样。
<ip> 主节点的 IP 地址,<redis-port>主节点的端口号。
<quorum>主节点对应的 quorum 法定数量,用于定义 Sentinel 的数量,是一个大于值尽量使用奇数,如果 Sentinel 有 3 个,则指定为 2 即可,如果有 4 个,不能够指定为 2,避免导致集群分裂。最后的数字 2 指定的值,表明如果有 2 个 sentinels 无法连接 master,才认为 master 挂了。quorum [ˈ kwɔ :rə m] 法定人数
改:# sentinel down-after-milliseconds <master-name> <milliseconds>
为:sentinel down-after-milliseconds mymaster 10000 #默认单位是毫秒,配成 10 秒
sentinel parallel-syncs mymaster 1 #保存默认parallel [ˈ pærəlel] 平行
改:sentinel failover-timeout mymaster 180000
为:sentinel failover-timeout mymaster 60000
-
把 redis-sentinel.conf 发给 另外2台 slave
- 登录 redis 查看 同步状态 信息
- 测试插入数据
- 模拟故障 停止 2.23 的 redis
- 查看日志
- 恢复 2.23
- 主 redis 还是 2.24,并不会因为 2.23 恢复成功后,就主动让出权限。 这样可以避免再次回切时,发生服务中断
- 查看 Sentinel 信息
- redis-cli -h 192.168.2.23 -p 26379
192.168.2.23:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.2.24:6379,slaves=2,sentinels=4
192.168.2.23:26379>
- 注意:将来客户端应连接 Sentinel,向 Sentinel 发请求去寻址,并根据 Sentinel 的反馈,进行连接新的 Redis 主节点,这一点需要使用 Redis 专用客户端来实现。Redis 客户端会根据 Sentinel 返回的新节点 IP 进行连接。这一块是开发人员的事情了。如果 java 中的 JedisClient 就提供了使用 Sentinel的功能。