网站的系统建设方式有哪些方面,教育机构做网站素材,wordpress做博客好吗,全球网站流量排名100Redis进阶配置
一、Redis持久化操作
持久化就是把内存的数据写到磁盘中去#xff0c;防止服务宕机了内存数据丢失。#xff08;Redis 数据都放在内存中。如果机器挂掉#xff0c;内存的数据就不存在。所以需要做持久化#xff0c;将内存中的数据保存在磁盘#xff0c…Redis进阶配置
一、Redis持久化操作
持久化就是把内存的数据写到磁盘中去防止服务宕机了内存数据丢失。Redis 数据都放在内存中。如果机器挂掉内存的数据就不存在。所以需要做持久化将内存中的数据保存在磁盘下一次启动的时候就可以恢复数据到内存中。 Redis 提供了两种持久化方式: RDB默认rbd 就是之前说的快照Redis DataBase 和 AOFAppend Of File)。
1.1 RDB持久化(快照)
Redis 可以通过创建快照来 获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后可以对快照进行备份可以将快照复制到其他服务器从而创建具有相同数据的服务器副本还可以将快照留在 本地以便重启服务器的时候使用。
1.1.1 RDB持久化流程
Redis会单独创建fork一个子进程来进行持久化会先将数据写入到 一个临时文件中待持久化过程都结束了再用这个临时文件替换上次持久化好的文件。 整个过程中主进程是不进行任何IO操作的这就确保了极高的性能 如果需要进行大规模数据的恢复且对于数据恢复的完整性不是非常敏感那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。 1.1.2 RDB 持久化触发策略
RDB持久化提供了两种触发策略一种是手动触发另一种是自动触发。 手动触发策略 手动触发是通过SAVE命令或者BGSAVE命令将内存数据保存到磁盘文件中。如下所示 save会阻塞当前Redis服务器直到持久化完成线上应该禁止使用。 bgsave该触发方式会fork一个子进程由子进程负责持久化过程因此阻塞只会发生在fork子进程的时候。
127.0.0.1:6379 SAVE
OK
127.0.0.1:6379 BGSAVE
Background saving started
127.0.0.1:6379 LASTSAVE
(integer) 1611298430自动触发策略 自动触发策略是指 Redis 在指定的时间内数据发生了多少次变化时会自动执行BGSAVE命令。自动触发的条件包含在了 Redis 的配置文件中( redis.conf 配置文件)如下所示 上图所示 save m n 的含义是在时间 m 秒内如果 Redis 数据至少发生了 n 次变化那么就自动执行BGSAVE命令。配置策略说明如下 save 900 1 表示在 900 秒内至少更新了 1 条数据Redis 自动触发 BGSAVE 命令将数据保存到硬盘。save 300 10 表示在 300 秒内至少更新了 10 条数据Redis 自动触 BGSAVE 命令将数据保存到硬盘。save 60 10000 表示 60 秒内至少更新了 10000 条数据Redis 自动触发 BGSAVE 命令将数据保存到硬盘。 只要上述三个条件任意满足一个服务器就会自动执行BGSAVE命令。当然您可以根据实际情况自己调整触发策略。
1.1.3 dump.rdb 文件 在 **redis.conf ** 中配置文件名称默认为 dump.rdb. RDB 文件的保存路径也可以修改。 默认为Redis启动时命令行所在的目录下我们可以自定义目录位置。 stop-writes-on-bgsave-error 当 Redis 无法写入磁盘的话直接关掉Redis的写操作。推荐Yes 1.2 AOF 持久化只追加文件
以日志的形式来记录每个写操作增量保存将Redis执行过的所有写指令记录下来(读操作不记录) 只许追加文件但不可以改写文件redis启动之初会读取该文件重新构建数据换言之redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
注意AOF默认不开启可以通过 appendonly 参数开启appendonly yes。可以在redis.conf中配置文件名称默认为 appendonly.aof。AOF文件的保存路径同RDB的路径一致。 AOF和RDB同时开启系统默认取AOF的数据数据不会存在丢失。
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令Redis 就会将该命令写入硬盘中的 AOF 文件。AOF 文件的保存位置和 RDB 文件的位置相同都是通过 dir 参数设置的默认的文件名是 appendonly.aof。 1.2.1 AOF 持久化策略 appendfsync always 始终同步每次Redis的写入都会立刻记入日志性能较差但数据完整性比较好。这样会严重降低 Redis的速度。 appendfsync everysec 每秒同步每秒记入日志一次如果宕机本秒的数据可能丢失。 appendfsync no redis不主动进行同步把同步时机交给操作系统。 为了兼顾数据和写入性能用户可以考虑 appendfsync everysec 选项 让 Redis 每秒同步一次 AOF 文件Redis 性能几乎没受到任何影响。而且这样即使出现系统崩溃用户最多只会丢失一秒之内产生的数 据。 1.2.2 ReWrite重写机制
AOF采用文件追加方式文件会越来越大为避免出现此种情况新增了重写机制, 当AOF文件的大小超过所设定的阈值时Redis就会启动AOF文件的内容压缩 只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof 如何重写? AOF文件持续增长而过大时会fork出一条新进程来将文件重写(也是先写临时文件最后再rename)redis4.0版本后的重写是指上就是把rdb 的快照以二级制的形式附在新的aof头部作为已有的历史数据替换掉原来的流水账操作。 no-appendfsync-on-rewrite 如果 no-appendfsync-on-rewriteyes ,不写入aof文件只写入缓存用户请求不会阻塞但是在这段时间如果宕机会丢失这段时间的缓存数据。降低数据安全性提高性能 如果 no-appendfsync-on-rewriteno, 还是会把数据往磁盘里刷但是遇到重写操作可能会发生阻塞。数据安全但是性能降低 触发机制何时重写 Redis会记录上次重写时的AOF大小默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发 重写虽然可以节约大量磁盘空间减少恢复时间。但是每次重写还是有一定的负担的因此设定Redis要满足一定条件才会进行重写。 auto-aof-rewrite-percentage设置重写的基准值文件达到100%时开始重写文件是原来重写后文件的2倍时触发 auto-aof-rewrite-min-size设置重写的基准值最小文件64MB。达到这个值开始重写。
例如文件达到70MB开始重写降到50MB下次什么时候开始重写100MB
系统载入时或者上次重写完毕时Redis会记录此时AOF大小设为base_size,
如果Redis的AOF当前大小 base_size base_size*100% (默认)且当前大小64mb(默认)的情况下Redis会对AOF进行重写。 1.2.3 使用AOF持久化流程
bgrewriteaof触发重写判断是否当前有bgsave或bgrewriteaof在运行如果有则等待该命令结束后再继续执行。主进程fork出子进程执行重写操作保证主进程不会阻塞。子进程遍历redis内存中数据到临时文件客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。 子进程写完新的AOF文件后向主进程发信号父进程更新统计信息。主进程把aof_rewrite_buf中的数据写入到新的AOF文件。 使用新的AOF文件覆盖旧的AOF文件完成AOF重写。 优势 备份机制更稳健丢失数据概率更低。可读的日志文本通过操作AOF稳健可以处理误操作。 劣势 比起RDB占用更多的磁盘空间。 恢复备份速度要慢。 每次读写都同步的话有一定的性能压力。 同时开启两种持久化方式:在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据, 因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整. RDB 的数据不实时同时使用两者时服务器重启也只会找 AOF 文件。那要不要只使用 AOF 呢 不推荐因为 RDB 更适合用于备份数据库(AOF 在不断变化不好备份) 快速重启而且不会有 AOF 可能潜在的 bug留着作为一个万一的手段。二、redis主从读写分离架构设计
之前我们仅仅是在一台 Redis 服务中操作数据 但是如果是高并发访问的情况下一台 redis 服务可能扛不住为了解决这样的问题可以配置多台 Redis 实现数据的同步这些 Redis服务之间是主master从slave关系。
主机数据更新后根据配置和策略 自动同步到备机的机制。主机就是master备机就是slave。主从复制的机制能干嘛
读写分离性能扩展。从而提高了访问的性能。容灾快速恢复可以很好的实现数据的备份。 2.1 搭建一主多从
现在需要准备三台 redis 服务所以需要三个 redis 配置文件同时要使用到三个端口分别是 6379,6380,6381。
另一种方案是准备三台虚拟机 (暂不使用该方案)。
详细操作创建堕胎机器
拷贝多个 redis.conf 文件开启 daemonize yespid 文件名称 (pidfile)指定端口 portLog 文件名称 (可以不配置)dump.rdb 名称 (dbfilename)appendonly 关掉 搭建步骤
新建一个目录存放redis的配置文件
#新建目录
mkdir myredis
cd myredis/
# 拷贝原有Redis的配置文件 redis.conf 到新创建的文件夹中(注意自己的原始 redis.conf 存放位置)
cp /usr/local/bin/redis.conf redis.conf在自定义创建的文件下 在创建三个配置文件
新建redis6379.conf、redis6380、redis6381 三个配置文件并在配置文件中定义以下内容
#redis6379.conf 配置文件内容
port 6379
bind 0.0.0.0
daemonize yes
save 900 1
dbfilename dump6379.rdb
dir /usr/local/redis/data
pidfile /usr/local/redis/run/redis-6379.pid
logfile /usr/local/redis/logs/redis-6379.log#
#redis6380.conf 配置文件内容
port 6380
bind 0.0.0.0
daemonize yes
save 900 1
dbfilename dump6380.rdb
dir /usr/local/redis/data
pidfile /usr/local/redis/run/redis-6380.pid
logfile /usr/local/redis/logs/redis-6380.log
slaveof 127.0.0.1 6379
masterauth hellosun#
#redis6381.conf 配置文件内容
port 6381
bind 0.0.0.0
daemonize yes
save 900 1
dbfilename dump6381.rdb
dir /usr/local/redis/data
pidfile /usr/local/redis/run/redis-6381.pid
logfile /usr/local/redis/logs/redis-6381.log
slaveof 127.0.0.1 6379
masterauth hellosu**bind 0.0.0.0 **在服务器的环境中指的就是当前服务器上所有的 ip 地址如果机器上有 2 个 ip 192.168.30.10 和 10.0.2.15redis 在配置中如果配置监听在 0.0.0.0 这个地址上那么通过这 2 个 ip 地址都是能够到达这个 redis 服务的。同时呢访问本地的 127.0.0.1 也是能够访问到 redis 服务的。save 900 1: 表示 15 分钟持久化一次数据将内存中的数据同步保存到磁盘中)bfilename dump6381.rdb持久化的文件**slaveof 127.0.0.1 6379:**表示当前 redis 服务的主主机master)**masterauth hellosun**表示 master 机的密码 启动三台 redis-server 注意这里需要调用 redis-server命令。需要配置好该命令如果找不着该命令就去对应的bin目录下执行redis-server /www/server/redisMyssss/redis3679.conf 命令。 [rootjava2201 redisMyss]# redis-server redis6379.conf
[rootjava2201 redisMyss]# redis-server redis6380.conf
[rootjava2201 redisMyss]# redis-server redis6381.conf
[rootjava2201 redisMyss]# ps -ef | grep redis
root 3012 1 0 14:45 ? 00:00:00 redis-server 127.0.0.1:6379
root 3018 1 0 14:46 ? 00:00:00 redis-server 127.0.0.1:6380
root 3024 1 0 14:46 ? 00:00:00 redis-server 127.0.0.1:6381
root 3030 2541 0 14:46 pts/0 00:00:00 grep --colorauto redis配置从机上面配置文件中已经设置 在6380 、6381 两个redis服务上配置从机角色。6379 是主机不需要做任何配置。 首先我们关掉redis三台服务器 [rootjava2201 redisMyss]# redis-cli -p 6379 shutdown
[rootjava2201 redisMyss]# redis-cli -p 6380 shutdown
[rootjava2201 redisMyss]# redis-cli -p 6381 shutdown在 redis6380.conf 、redis6381.conf 配置文件中配置从机在配置文件中添加 slaveof 127.0.0.1 6379 重启三台redis服务器查询相关的服务器运行信息。 首先使用 redis-cli -p 命令使用客户端连接服务器( 注意如果设置密码的从机需要登录密码 )然后使用命令info replication 查看redis服务器运行情况。 #查看 master(主机 redis6379) 的运行情况
[rootjava2201 redisMyss]# redis-cli -p 6379
127.0.0.1:6379 info replication
# Replication
role:master # 主机
connected_slaves:2 # 从机的数量
slave0:ip127.0.0.1,port6380,stateonline,offset42,lag0 # 从机的具体状态
slave1:ip127.0.0.1,port6381,stateonline,offset28,lag1 # 从机的具体状态
master_failover_state:no-failover
master_replid:df8e8d5239e9e60712e03aef99e38dc2954ef428
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:42查看 slave(从机 redis6380、redis6381) 的运行情况
[rootjava2201 redisMyss]# redis-cli -p 6380
127.0.0.1:6380 info replication
Replication
role:slave # 角色 从机
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:56
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:df8e8d5239e9e60712e03aef99e38dc2954ef428
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56测试reids主从复制是否成功
在主机上添加数据在从机上查看
#在redis6379机器上设置数据
127.0.0.1:6379 set username eric
OK#在从机redis6380 redis6381上查看数据
127.0.0.1:6380 get username
eric
127.0.0.1:6381 get username
eric在从机上写数据看是否可以写成功。
127.0.0.1:6380 set k1 v1
(error) READONLY You cant write against a read only replica.
# 不能写数据因为从机只能读数据127.0.0.1:6381 set k2 v2
(error) READONLY You cant write against a read only replica.
# 不能写数据因为从机只能读数据2.2 主从复制原理
首先测试一个几个问题会发生的情况
2.2.1 从机挂掉后的情况
这里先停掉redis6381这台机器。然后在主机6379上新增一个数据( 此时redis6381从机已经关闭 )登录到6380这台从机上去获取新增的数据查看效果重启redis6381 这台从机查询挂掉期间主机上新增的数据看是否能够获取到
# 1.停掉redis6381
127.0.0.1:6381 shutdown
not connected exit[rootjava2201 redisMyss]# ps -ef | grep redis
root 3956 1 0 15:49 ? 00:00:00 redis-server 127.0.0.1:6379
root 3962 1 0 15:49 ? 00:00:00 redis-server 127.0.0.1:6380
root 3975 3807 0 15:49 pts/0 00:00:00 redis-cli -p 6379
root 3987 3864 0 15:49 pts/1 00:00:00 redis-cli -p 6380
root 4002 3905 0 15:50 pts/2 00:00:00 grep --colorauto redis# 2.主机上新增数据
127.0.0.1:6379 set k1 v1
OK
127.0.0.1:6379 keys *
1) username
2) k1# 3.登录到从机6380 查看情况
127.0.0.1:6380 keys *
1) k1
2) username# 4.重启之前关闭的从机redis6381
[rootjava2201 myredis]# redis-server redis6381.conf
[rootjava2201 myredis]# redis-cli -p 6381
127.0.0.1:6381 info replication
# Replication
role:slave # 重启之后 角色没有发生变化依然是从机
master_host:127.0.0.1
master_port:6379# 4.重启后的从机6381中查询主机增加的数据
127.0.0.1:6381 keys *
1) k1 # 依然能够同步到主机上最新的数据
2) username2.2.2 主机挂掉后的情况
这里将主机进行挂掉操作然后在从机中查看从机的状态是否发生变化。
# 1.将主机redis6379 关闭
127.0.0.1:6379 shutdown
not connected exit
[rootjava2201 myredis]# ps -ef | grep redis
root 3962 1 0 15:49 ? 00:00:00 redis-server 127.0.0.1:6380
root 3987 3864 0 15:49 pts/1 00:00:00 redis-cli -p 6380
root 4022 1 0 15:52 ? 00:00:00 redis-server 127.0.0.1:6381
root 4036 3905 0 15:53 pts/2 00:00:00 redis-cli -p 6381
root 4054 3807 0 15:55 pts/0 00:00:00 grep --colorauto redis# 2.查看两个从机的状态变化
127.0.0.1:6380 info replication # 从机6380机器上的状态
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down127.0.0.1:6381 info replication # 从机6381机器上的状态
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down可以看出不管主机的状态是什么样从机的角色永远不会发生变化。
2.2.3 主从复制的原理 Slave启动成功连接到master后会发送一个sync命令。Master接到命令启动后台的存盘进程同时收集所有接收到的用于修改数据集命令 在后台进程执行完毕之后master将传送整个数据文件到slave,以完成一次完全同步。全量复制而slave服务在接收到数据库文件数据后将其存盘并加载到内存中。增量复制Master继续将新的所有收集到的修改命令依次传给slave,完成同步。但是只要是重新连接master,一次完全同步全量复制)将被自动执行。 2.3 其它配置方式
2.3.1 薪火相传
上一个Slave可以是下一个slave的MasterSlave同样可以接收其他 slaves的连接和同步请求那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险。
风险是一旦某个slave宕机后面的slave都没法备份。
现在我们实现薪火相传的效果:
搭建redis6382,注意redis6382是redis6381的从机。
[rootjava2201 myredis]# vim redis6382.conf# 配置文件内容
include /myredis/redis.conf
pidfile /var/run/redis_6382.pid
port 6382
dbfilename dump6382.rdb
slaveof 127.0.0.1 6381 # 不是6379#启动 redis6382 客户端在查询他的状态
[rootjava2201 myredis]# redis-cli -p 6382
127.0.0.1:6382 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381 # 我们发现6381是6382的主机在查询 redis6381的状态 我们发现redis6380既是从机还是6382的主机。
注意:6381还是只能提供读的服务不能写数据它的作用是分担了6379机器数据同步的压力。 2.3.2 反客为主
在默认情况下如果主机挂了从机的角色不会发生变化永远都是从机的角色。如果我们想主机挂了之后从机的角色发生转换转换成主机这就叫反客为主。 关闭主机redis6379 127.0.0.1:6379 shutdown
not connected exit把从机redis6380设置成主机 127.0.0.1:6380 slaveof no one
OK
127.0.0.1:6380 info replication
# Replication
role:master
127.0.0.1:6380 set k2 v2 # 可以存数据了
OK在从机上取数据 127.0.0.1:6381 slaveof 127.0.0.1 6380 # 重新指定其主机是6380
OK
127.0.0.1:6381 keys *
1) k1
2) username
3) k2
127.0.0.1:6381 get k2
v22.4 哨兵模式
反客为主的自动版能够后台监控主机是否故障如果故障了根据投票数自动将从节点切换成主节点。
在之前配置的 Redis 主从服务中可以实现数据的备份也实现了读写分离master 负责写入和更新数据slave 负责读取数据但是还是存在一定的问题一旦 master 死掉比如网络出问题之后就无法写入数据了所以其实上之前的架构设计还很脆弱容灾能力不强。
如果 master 宕机了整个系统无法写入数据很可能让系统瘫痪给企业带来损失最直观的是影响了口碑等影响。
最好的做法是当 master 死掉之后会在 slave 中通过一定算法不用你实现选举出一台新的 master。要实现这个操作需要配置哨兵对整个集群环境进行监控一旦有两个或者两个以上的哨兵数量是可以配置认为当前的master 出问题了最终就从 slave 中选举出一台新的 master从而解决问题。 关于哨兵机制的配置我们不需要额外下载任何安装包之类的东西在我们安装 redis 的时候就已经自带了所以我们只需要拷贝相关的启动文件和配置文件进行配置即可。 2.4.1 搭建哨兵模式步骤 如果要进行哨兵进程的启动那么一定需要有一个哨兵程序启动文件 redis-sentinel (在reids的安装目录中)该文件自动会保存在编译后的 Redis 目录中将该启动文件拷贝到 redis 的bin 目录中。 cp /usr/local/src/redis/src/redis-sentinel /usr/local/redis/bin/ 将 sentinel.conf 拷贝到 我们 将官方自带的哨兵配置文件 sentinel.conf (此文件在 redis 的源码目录下即解压路径下复制到存放主从机配置文件中(根据自己的存放位置进行拷贝) cp /usr/local/src/redis/sentinel.conf /usr/local/redis/conf/ 哨兵机制中各配置项的含义 其中mymaster为监控对象起的服务器名称 NO配置项作用模式1protected-mode no在 redis.conf 的配置文件中关闭 redis 的保护模式如果不关闭 redis 的保护模式则哨兵无法实现主从切换无法自动修改配置文件选举出新的 maste2port 26379配置哨兵服务的端口3sentinel monitor mymaster 127.0.0.16379 2设置哨兵监控的名称192.168.139.134 63792 表 示 master 的 ip 地址,端口号, 2 指明当有两个 sentinel 认为 master 失效时master 才算真正失效4sentinel auth-pass mymaster hellosu配置 master 的密码(如没设置密码可以省略5sentinel down-after-milliseconds mymaster 5000master 宕机之后指定时间才会被 sentinel 主观地认为是不可用的单位是毫秒默认为 30 秒。6sentinel failover-timeout mymaster 18000配置选举新的 master 超时时间切换时间单位是毫秒如果超过了该时间认为切换失败整个服务就完了7pidfile/usr/data/redis/run/redis-sentinel.pid哨兵进程文件的保存目录与 Redis 进程目录相同8#logfile “/usr/data/redis/logs/sentinel-26379.log”设置哨兵日志文件所在的路径如果此时希望信息前台显示输出,则暂时不进行此内容的设置9dir /usr/local/redis/data 【但是你要在系统中创建该目录】指定一些临时数据的保存目录10daemonize no是否为后台运行如果设置为 yes 表示后台运行实际开发中要设置为 yes 将如下的配置复制到三台 slave 机中的 sentinel.conf 文件 port 26379
daemonize no
pidfile /usr/data/redis/run/redis-sentinel.pid
# logfile /usr/data/redis/logs/sentinel-26379.log
dir /usr/local/redis/data
sentinel monitor mymaster 192.168.139.134 6379 2
sentinel auth-pass mymaster hellosun
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 180002.4.2 启动哨兵
[rootjava2201 conf]# redis-sentinel sentinel.conf我们可以看到哨兵监控的具体信息: 将主机redis6379停掉: [rootjava2201 myredis]# redis-cli -p 6379 shutdown我们再看sentinel控制台的输出(此时需要等待一定的时间)我们可以看到切换主机的一些日志信息 查看redis6381的服务器运行信息 [rootjava2201 ~]# redis-cli -p 6381
127.0.0.1:6381 info replication
# Replication
role:master # 变成了主机
connected_slaves:1
slave0:ip127.0.0.1,port6380,stateonline,offset36593,lag0
master_failover_state:no-failover
master_replid:b6ff983efa23cafad22380a6d9d270eadcb69e99
master_replid2:8b338cbee4b296b50621911fd89d26d68c110b14
master_repl_offset:36593
second_repl_offset:14976
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:36593接下来我们重新启动redis6379服务器 [rootjava2201 myredis]# redis-cli -p 6379 shutdown
[rootjava2201 myredis]# redis-server redis6379.conf
[rootjava2201 myredis]# redis-cli -p 6379
127.0.0.1:6379 info replication
# Replication
role:slave # 6379变成了从服务器了
master_host:127.0.0.1
master_port:63812.4.3 哨兵的选举策略
通过上面的操作我们指定当从节点挂掉之后哨兵会选出新的主节点他们选举策略如下
(1) 选择优先级靠前的。
优先级在redis.conf中默认replica-priority 100值越小优先级越高 (2) 选择偏移量最大的。
偏移量是指获得原主机数据最全的。
(3) 选择runid最小的服务。
每个redis实例启动后都会随机生成一个40位的runid。 2.5 Spring整合哨兵机制
实现了哨兵机制的集群架构配置此时如果原先的 master 服务宕机了要求也不影响程序的访问程序也能找到新的 master 机进行数据操作要实现这个需求需要在项目中进行一些整合配置我们就以 SpringDataRedis 作为案例进行整合配置。 三、redis集群
如果redis容量不够了数据写不进去了redis如何扩容?
如果redis的并发操作大redis如何分摊并发压力?
另外主从模式薪火相传模式主机宕机导致ip地址发生变化应用程序中配置需要修改对应的主机地址、端口等信息。之前通过代理主机来解决但是redis3.0中提供了解决方案。就是无中心化集群配置。 3.1 搭建redis集群
redis集群有什么特点Redis 集群实现了对Redis的水平扩容即启动N个redis节点将整个数据库分布存储在这N个节点中每个节点存储总数据的1/N。
Redis 集群通过分区partition来提供一定程度的可用性availability 即使集群中有一部分节点失效或者无法进行通讯 集群也可以继续处理命令请求。
接下来我们开始redis集群的具体搭建 创建新的目录
创建目录redis-cluster将之前搭建主从复制的redis.conf拷贝到当前目录。
注意redis.conf配置文件一定要设置成远程登录否则搭建集群不成功。
[rootjava2201 /]# mkdir redis-cluster
[rootjava2201 /]# cd redis-cluster
[rootjava2201 redis-cluster]# cp /myredis/redis.conf redis.conf我们搭建3主3从所以我们创建6个redis实例。
6个redis实例的端口号分别是6379,6380,6381,6389,6390,6391。
创建redis配置文件redis6379.conf配置文件里面定义如下:
include /redis-cluster/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000注意
cluster-enabled yes 打开集群模式
cluster-config-file nodes-6379.conf 设定节点配置文件名
cluster-node-timeout 15000 设定节点失联时间超过该时间毫秒集群自动进行主从切换。 复制其他节点的配置文件
[rootjava2201 redis-cluster]# cp redis6379.conf redis6380.conf
[rootjava2201 redis-cluster]# cp redis6379.conf redis6381.conf
[rootjava2201 redis-cluster]# cp redis6379.conf redis6389.conf
[rootjava2201 redis-cluster]# cp redis6379.conf redis6390.conf
[rootjava2201 redis-cluster]# cp redis6379.conf redis6391.conf
[rootjava2201 redis-cluster]# ll
总用量 24
-rw-r--r--. 1 root root 177 10月 6 19:57 redis6379.conf
-rw-r--r--. 1 root root 177 10月 6 20:01 redis6380.conf
-rw-r--r--. 1 root root 177 10月 6 20:01 redis6381.conf
-rw-r--r--. 1 root root 177 10月 6 20:01 redis6389.conf
-rw-r--r--. 1 root root 177 10月 6 20:01 redis6390.conf
-rw-r--r--. 1 root root 177 10月 6 20:01 redis6391.conf将配置文件里面的内容进行修改
可以使用查找并替换的命令来实现:
:%s/6379/6380启动6个redis服务
[rootjava2201 redis-cluster]# redis-server redis6379.conf
[rootjava2201 redis-cluster]# redis-server redis6380.conf
[rootjava2201 redis-cluster]# redis-server redis6381.conf
[rootjava2201 redis-cluster]# redis-server redis6389.conf
[rootjava2201 redis-cluster]# redis-server redis6390.conf
[rootjava2201 redis-cluster]# redis-server redis6391.conf 查看redis服务启动状态:
[rootjava2201 redis-cluster]# ps -ef | grep redis
root 8673 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6379 [cluster]
root 8679 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6380 [cluster]
root 8685 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6381 [cluster]
root 8691 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6389 [cluster]
root 8697 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6390 [cluster]
root 8703 1 0 22:56 ? 00:00:00 redis-server 127.0.0.1:6391 [cluster]
root 8483 6637 0 22:45 pts/0 00:00:00 grep --colorauto redis注意如果搭建成功当前目录下面必须存在以nodes-开头的文件 将6个节点合并成一个集群
合并集群之前请确保所有redis实例启动后nodes-xxxx.conf文件都生成正常。
先进入到最先安装redis的src目录
[rootjava2201 /]# cd /opt/redis-6.2.1/src
[rootjava2201 src]# ls[rootjava2201 src]# redis-cli --cluster create --cluster-replicas 1 192.168.10.130:6379 192.168.10.130:6380 192.168.10.130:6381 192.168.10.130:6389 192.168.10.130:6390 192.168.10.130:6391注意此处不要用127.0.0.1 请用真实IP地址。
–replicas 1 采用最简单的方式配置集群一台主机一台从机正好三组。
执行命令之后效果如下: 我们输入yes表示接受以上配置 如果出现以上信息说明集群搭建成功。
连接集群
使用连接集群的命令 redis-cli -c -p 6379
-c:指的使用集群的方式连接redis。
-p指定参数这里任意参数都可以。
[rootjava2201 src]# redis-cli -c -p 6379
[rootjava2201 src]# cluster nodes # 查看集群的具体情况3.2 redis集群细节
一个集群至少要有三个主节点。
选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
分配原则尽量保证每个主数据库运行在不同的IP地址每个从库和主库不在一个IP地址上。 一个 Redis 集群包含 16384 个插槽hash slot 数据库中的每个键都属于这 16384 个插槽的其中一个。
集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分插槽。 举个例子 如果一个集群可以有主节点 其中
节点 A 负责处理 0 号至 5460 号插槽。
节点 B 负责处理 5461 号至 10922 号插槽。
节点 C 负责处理 10923 号至 16383 号插槽。 在集群模式写写入数据
接下来我们在集群中插入数据:
127.0.0.1:6379 set k1 v1
- Redirected to slot [12706] located at 192.168.10.140:6381
OK
192.168.10.140:6381 set k2 v2
- Redirected to slot [449] located at 192.168.10.140:6379
OK
192.168.10.140:6379注意不在一个slot下的键值是不能使用mget,mset等多键操作。
192.168.10.140:6379 mset username eric age 20
(error) CROSSSLOT Keys in request dont hash to the same slot # 此时报错我们可以通过{}来定义组的概念从而使key中{}内相同内容的键值对放到一个slot中去。
192.168.10.140:6379 mset username{group1} eric age{group1} 20
- Redirected to slot [7859] located at 192.168.10.140:6380
OK
192.168.10.140:6380查询集群中的值
192.168.10.140:6380 cluster keyslot k2 # 计算key的插槽值
(integer) 449
192.168.10.140:6380 get k1
- Redirected to slot [12706] located at 192.168.10.140:6381
v1
192.168.10.140:6381 get k2
- Redirected to slot [449] located at 192.168.10.140:6379
v2
192.168.10.140:6381 get username{group1}
- Redirected to slot [7859] located at 192.168.10.140:6380
eric
192.168.10.140:6380 get age{group1}
20redis集群的故障恢复
在redis集群中如果某一个主节点挂掉(下线)会出现什么样的后果
192.168.10.140:6379 shutdown # 将6379服务停掉
not connected exit现在我们重新启动6379这台机器我们重新打开一个终端来启动:
[rootjava2201 src]# cd /redis-cluster/
[rootjava2201 redis-cluster]# redis-server redis6379.conf 如果所有某一段插槽的主从节点都宕掉redis服务是否还能继续?
如果某一段插槽的主从都挂掉而cluster-require-full-coverage 为yes 那么 整个集群都挂掉
如果某一段插槽的主从都挂掉而cluster-require-full-coverage 为no 那么该插槽数据全都不能使用也无法存储。
redis.conf中的参数 cluster-require-full-coverage 四、redis其它
4.1 Redis 的使用场景 数据缓存提高访问性能 比如热点新闻就可以存到 redis 中。 如果数据在短时间之内不会发生变化而且它们还要被频繁访问为了提高用户的请求速度和降低网站的负载降低数据库的读写次数就把这些数据放到缓存中。 会话缓存共享 session session cache保存 web 会话信息替代了 ip_hash可以将用户的信息保存到 redis 中nginx 代理多个web服务器。 排行榜/计数器
做排行榜用 zset里面有分值就可以实现排行榜。NGINXredis 计数器进行 IP 自动封禁防止恶意攻击 消息队列ActiveMQ/RabbitMQ/Kafka/RocketMQ 生产者/消费者模型发布/订阅模式构建实时消息系统聊天群聊重点做缓存数据用户信息 4.2 LIMITS 限制 (淘汰策略) redis基础一文章中有说明过 保存到 redis 中的数据会被淘汰什么情况会被淘汰比如超时时间到了但是如果没有设置超时时间的数据如何淘汰 maxmemory 设置 redis 可以使用的内存量。一旦到达内存使用上限redis 将会试图移除内部数据移除规则可以过 maxmemory-policy 来指定。如果 redis 无法根据移除规则来移除内存中的数据或者设置了“不允许移除”那么 redis 则会针对那些需要申请内存的指令返回错误信息比如 SET、LPUSH 等。 maxmemory-policy noeviction当内存使用超过配置的时候会返回错误不会驱逐任何键不移除任何数据allkeys-lru加入键的时候如果过限首先通过 LRU 算法驱逐最近最久没有使用的键 【在指定的时间内某些 key 没有被使用就移出】volatile-lru加入键的时候如果过限首先从设置了过期时间的键集合中驱逐最久没有使用的键范围是设置了超时时间的 key 中查找allkeys-random加入键的时候如果过限从所有 key 随机删除volatile-random加入键的时候如果过限从过期键的集合中随机驱逐volatile-ttl从配置了过期时间的键中驱逐马上就要过期的键volatile-lfu从所有配置了过期时间的键中驱逐使用频率最少的键allkeys-lfu从所有键中驱逐使用频率最少的键 LRULeast recently used最近最少使用 LRU 最近最久没有使用的算法(对最近的表现做总结考虑不完善但是很容易实现) 如果一个数据最近一段时间都没有被访问到那么认为这个数据在将来访问的可能性也比较小因此当空间满时最久没有访问的数据最先被淘汰 LFU 使用频率最少的算法对历史数据做总结考虑更全面一些但是会耗费总结历史的时间 LFUleast frequently used (LFU) page-replacement algorithm 如果一个数据很少被访问到那么认为这个数据在将来访问的可能性也比较小因此当空间满时最小频率访问的数据最先被淘汰 4.3 Redis应用问题
4.3.1 缓存穿透 问题描述 key对应的数据在数据库并不存在每次针对此key的请求从缓存获取不到请求都会压到数据源从而可能压垮数据库。比如用一个不存在的用户id获取用户信息不论缓存还是数据库都没有若黑客利用此漏洞进行攻击可能压垮数据库。 解决方案 一个一定不存在缓存及查询不到的数据由于缓存是不命中时被动写的并且出于容错考虑如果从存储层查不到数据则不写入缓存这将导致这个不存在的数据每次请求都要到存储层去查询失去了缓存的意义。1 **对空值缓存**如果一个查询返回的数据为空不管是数据是否不存在我们仍然把这个空结果null进行缓存设置空结果的过期时间会很短最长不超过五分钟
2 设置可访问的名单白名单
使用bitmap类型定义一个可以访问的名单名单id作为bitmaps的偏移量每次访问和bitmap里面的id进行比较如果访问id不在bitmaps里面进行拦截不允许访问。
3 采用布隆过滤器**(布隆过滤器Bloom Filter是1970年由布隆提出的。它实际上是一个很长的二进制向量(位图)和一系列随机映射函数哈希函数。
布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法缺点是有一定的误识别率和删除困难。)
将所有可能存在的数据哈希到一个足够大的bitmaps中一个一定不存在的数据会被 这个bitmaps拦截掉从而避免了对底层存储系统的查询压力。
4 **进行实时监控**当发现Redis的命中率开始急速降低需要排查访问对象和访问的数据和运维人员配合可以设置黑名单限制服务 4.3.2 缓存击穿
缓存穿透是恶意的攻击行为。而缓存穿击是系统正常使用过程中出现了的某一个热点数据过期导致大量的请求去查询关系型数据库。 问题描述: key对应的数据存在但在redis中过期此时若有大量并发请求过来这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存这个时候大并发的请求可能会瞬间把后端DB压垮。解决方案 key可能会在某些时间点被超高并发地访问是一种非常“热点”的数据。这个时候需要考虑一个问题缓存被“击穿”的问题。**1预先设置热门数据**在redis高峰访问之前把一些热门数据提前存入到redis里面加大这些热门数据key的时长
**2实时调整**现场监控哪些数据热门实时调整key的过期时长[热点 key 永不过期过期时间相对较长避免出现淘汰策略]
3使用锁
3.1 就是在缓存失效的时候判断拿出来的值为空不是立即去load db。
3.2 先使用缓存工具的某些带成功操作返回值的操作比如Redis的SETNX去set一个mutex key
3.3 当操作返回成功时再进行load db的操作并回设缓存,最后删除mutex key
3.4 当操作返回失败证明有线程在load db当前线程睡眠一段时间再重试整个get缓存的方法。 4.3.3 缓存雪崩 问题描述 key对应的数据存在但在redis中过期此时若有大量并发请求过来这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存这个时候大并发的请求可能会瞬间把后端DB压垮。缓存雪崩与缓存击穿的区别在于这里针对很多key缓存前者则是某一个key。解决方案 **构建多级缓存架构**nginx缓存 redis缓存 其他缓存ehcache等用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写从而避免失效时大量的并发请求落到底层存储系统上。不适用高并发情况比如我们可以在原有的失效时间基础上增加一个随机值比如1-5分钟随机这样每一个缓存的过期时间的重复率就会降低就很难引发集体失效的事件。记录缓存数据是否过期设置提前量如果过期会触发通知另外的线程在后台去更新实际key的缓存。缓存数据的过期时间设置随机防止同一时间大量数据过期现象发生。如果缓存数据库是分布式部署将热点数据均匀分布在不同的缓存数据库中比如说有多台 redis 服务可以将热点数据分部在不同 redis 服务中。设置热点数据永远不过期
缓存穿透—人为恶意对某一个 key 进行查询导致的关系型数据库出现压力 缓存穿击—正常使用中某个热点数据过期导致的 关系型数据库出现的压力 缓存雪崩—大批量的热点数据同时过期给关系型数据库带来的查询压力