Redis缓存框架

1.Linux环境下安装Redis:

下载Redis安装包
wget http://download.redis.io/releases/redis-3.2.9.tar.gz

解压Redis安装包
tar -zxvf redis-3.2.9.tar.gz

安装
cd redis-3.2.9
make
cd src
make install PREFIX=/usr/local/redis

移动配置文件到安装目录下
cd …/
mkdir /usr/local/redis/etc
mv redis.conf /usr/local/redis/etc

修改redis配置
vi /usr/local/redis/etc/redis.conf
//将daemonize no 改成daemonize yes 设置为后台启动
// requirepass 123 设置redis密码
// 注释 bind 127.0.0.1 开启外网访问

开启redis
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

连接Redis客户端 需要进入到 cd src/
./redis-cli -h 127.0.0.1 -p 6379 -a “123”

ping 尝试
127.0.0.1:6379> ping
PONG //出现PONG 表示成功

停止redis服务
127.0.0.1:6379> SHUTDOWN
not connected>

2.配置一主多从:

修改slave从redis中的 redis.conf文件多从
vi /usr/local/redis/etc/redis.conf
slaveof 192.168.80.100(主服务器ip) 6379
masterauth 123(主服务器密码)
若开启哨兵模式,主服务器也需要修改这两项配置,哨兵切换主从会动态修改

3.集群需要关闭防火墙(主从都需要关闭):

//临时关闭
systemctl stop firewalld
//禁止开机启动
systemctl disable firewalld
禁止开机启动后若出现以下,表示成功
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

4.Redis主从复制:

主服务器有读和写的功能,从服务器只有读的功能
在这里插入图片描述

5.Redis哨兵模式集群:

在这里插入图片描述
哨兵作用:用于管理多个Redis服务器
1.监控:监控每一台服务器是否正常(包括master以及salve)
2.心跳检测
自动故障迁移:当master不能正常工作,哨兵会在slave中选取一个作为master,并且自动修改配置,当原master恢复正常后,将作为salve加入集群

6.Redis哨兵模式配置:

在redis目录下拷贝到etc目录
cp sentinel.conf /usr/local/redis/etc

修改sentinel.conf配置文件
vi /usr/local/redis/etc/sentinel.conf
sentinel monitor mymaster 192.168.80.100 6379 1 #主节点 名称 IP 端口号 选举次数
sentinel auth-pass mymaster 123 #设置密码
sentinel down-after-milliseconds mymaster 30 #修改心跳检测30毫秒
sentinel parallel-syncs mymaster 2 #做多多少合格节点

启动哨兵模式 cd src/
./redis-server /usr/local/redis/etc/sentinel.conf --sentinel &

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.Redis持久化:

Redis有两种持久化,RDB以及AOF
1).RDB模式:
Redis默认开启RDB模式,该模式主要有两个参数构成,时间和改动键值的个数,指定时间内改动的键的个数大于设置的键值数时,就会进行快照保存
a.设置触发条件:
在这里插入图片描述
在这里插入图片描述
注意:在redis正常退出的时候 即使没有达到save 的情况 也会进行保存持久化 例如 我现在 操作10个key 在300s以内 会保存。。但是我只操作了9个 退出 redis 他也会持久化保存,但是 如果是断电或者kill-9 杀死进程 则不会保存

b.设置RDB文件名以及存放路径:
在这里插入图片描述
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下启动的redis-cli,则数据会存储在当前src目录下

c.RDB文件的压缩:
RDB默认开启文件压缩模式 压缩会损耗CPU,可以减少磁盘储存空间在这里插入图片描述
d.RDB快照过程
Redis用fork函数复制一份主进程的副本,主进程继续接收客服端发来的命令,子进程将内存中的数据写到硬盘中的临时文件,当子进程完成写入后临时文件代替原文件

e.手动快照
如果没有启动自动快照,可使用save,bgsave命令进行手动快照
save:由主进程进行快照模式,会阻塞其他操作
bgsave:通过fork子进程进行快照模式
快照命令:./redis-cli -h 127.0.0.1 -p 6379 bgsave
在这里插入图片描述
RDB优点:使用单独的子进程进行持久化,主进程不会有任何的IO操作,保证redis的高性能
RDB缺点:RDB模式是时隔一段时间进行快照保存,若在持久化之间发生故障,会导致部分数据丢失(上一次持久化–发生故障,这段时间的数据丢失)

2).AOF模式
AOF类似日志记录,来一条记录一条,记录redis客户端每一条命令,所以aof文件比rdb文件大得多
a.开启aof
默认aof是关闭的
##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
##只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly yes
##指定aof文件名称
appendfilename appendonly.aof
在这里插入图片描述

b.文件重写
由于AOF是将每一个命令记录下来,所以必定存在该现象对同一个key进行多次操作

  • 同一个key的多次写入只保留最后一个命令
  • 已删除、已过期的key的写命令不再保留
    举个例子:比如在redis客户端对key执行了一系列命令
    set aaa 1 //初始值为1
    incr aaa// 加1
    incr aaa//加1
    decr aaa//减1
    如果不进行重写 如图 aof文件会将所有命令记录下来
    在这里插入图片描述
    在这里插入图片描述
    对AOF进行重写,会直接记录结果 相当于set aaa 2
    运行该命令: ./redis-cli -h 127.0.0.1 -p 6379 -a “123” bgrewriteaof
    在这里插入图片描述在这里插入图片描述

c.重写策略
##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
appendfsync everysec (推荐)
always:每一条操作都记录,易造成阻塞
everysec:每一秒记录,就算发生故障也只是丢失前一秒的数据
no:交给系统处理,视buffer的填充情况

auto-aof-rewrite-min-size 64MB
当AOF文件小于64MB的时候不进行AOF重写
auto-aof-rewrite-min-percenrage 100
当前AOF文件比上次AOF重写后的文件大100%的时候进行AOF重写

AOF重写也是启动子进程进行重写操作

8.Redis-Cluster集群:

在这里插入图片描述
a.架构细节:
1).所有redis节点互联(PING-PONG机制),内部使用二进制协议优化传输数据和带宽
2).必须超过半数的节点检测失效才算节点fail
3).客户端与redis节点直连,不需要proxy层,客户端不需要连接集群中所有节点,只需连接其中一个
4).redis-cluster把所有的物理节点映射到[0-16383]slot槽上,cluster 负责维护node<->slot<->value
5).Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点!

b.Redis-Cluster 容错
1).如何判断单个master不可用,所有master参与投票,当半数以上的master与其中一个master通讯超过cluster-node-timeout,则该master不可用
总结为:半数以上master与master b通信超时,b不可用
2).如何判断整个集群不可用:a.如果集群任意master挂掉,且当前master没有slave(哈希槽找不到对应的master映射),b.当集群中的超过半数的master挂掉,无论它是否有对应的salve,该集群都不可用
总结为:当master挂掉没有salve顶替,集群不可用 超半数master都挂掉,集群不可用

9.Redis-Cluster搭建:

(一台虚拟机6个端口伪集群搭建,redis不设置密码以便搭建)
端口号:9001-9006 创建端口号文件夹存放各个实例redis文件,数据存放在/data文件夹中
mkdir /usr/local/redis-cluster
cd /usr/local/redis-cluster
mkdir -p 9001/data 9002/data 9003/data 9004/data 9005/data 9006/data

在redis-cluster文件夹下创建bin目录,存放集群运行的脚本文件,这些文件在/src目录下拷贝
cd /usr/local/redis-cluster
mkdir bin
cd /redis-3.2.9/src
cp mkreleasehdr.sh redis-benchmark redis-check-aof redis-cli redis-server redis-trib.rb /usr/local/redis-cluster/bin

复制一个redis实例到9001,并且修改该conf
cp -r /usr/local/redis /usr/local/redis-cluster/9001

修改redis.conf
port 9001(每个节点的端口号)
daemonize yes (后台运行redis)
bind 192.168.80.99(绑定当前机器 IP)
pidfile /var/run/redis_9001.pid(pid 9001和port要对应)
cluster-enabled yes(启动集群模式)
cluster-config-file nodes9001.conf(9001和port要对应)
cluster-node-timeout 15000 (集群中各master节点的容错时间,若超过该时间,master挂掉)
appendonly yes
在conf文件最后添加
dir /usr/local/redis-cluster/9001/data/(数据文件存放位置)

再复制出五个新实例,进而替换9001即可
cp -rf /usr/local/redis-cluster/9001/* /usr/local/redis-cluster/9002
cp -rf /usr/local/redis-cluster/9001/* /usr/local/redis-cluster/9003
cp -rf /usr/local/redis-cluster/9001/* /usr/local/redis-cluster/9004
cp -rf /usr/local/redis-cluster/9001/* /usr/local/redis-cluster/9005
cp -rf /usr/local/redis-cluster/9001/* /usr/local/redis-cluster/9006

修改redis.conf文件替换端口
vi /usr/local/redis-cluster/9002/redis/etc/redis.conf
%s/9001/9002
vi /usr/local/redis-cluster/9003/redis/etc/redis.conf
%s/9001/9003
vi /usr/local/redis-cluster/9004/redis/etc/redis.conf
%s/9001/9004
vi /usr/local/redis-cluster/9005/redis/etc/redis.conf
%s/9001/9005
vi /usr/local/redis-cluster/9006/redis/etc/redis.conf
%s/9001/9006

启动9001-9006六个节点
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9001/redis/etc/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9002/redis/etc/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9003/redis/etc/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9004/redis/etc/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9005/redis/etc/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/9006/redis/etc/redis.conf

查看启动进程 ps aux | grep redis

进入任意一个客户端操作
/usr/local/redis-cluster/9001/redis/bin/redis-cli -c -h 192.168.80.99 -p 9001
操作会报错:(error) CLUSTERDOWN Hash slot not served
这是因为虽然我们配置并启动了 Redis 集群服务,但是他们暂时还并不在一个集群中,互相直接发现不了,而且还没有可存储的位置,就是所谓的slot(槽)。

安装集群所需要的软件
因为集群软件是用ruby编写的
yum install ruby
yum install rubygems
从本地上传redis-3.2.1.gem
gem install -l redis-3.2.1.gem
在这里插入图片描述
开启集群环境
/usr/local/redis-cluster/bin/redis-trib.rb create --replicas 1 192.168.80.99:9001 192.168.80.99:9002 192.168.80.99:9003 192.168.80.99:9004 192.168.80.99:9005 192.168.80.99:9006
在这里插入图片描述
调用 ruby 命令来进行创建集群,–replicas 1 表示主从复制比例为 1:1,即一个主节点对应一个从节点;然后,默认给我们分配好了每个主节点和对应从节点服务,以及 solt 的大小,因为在 Redis 集群中有且仅有 16383 个 solt ,默认情况会给我们平均分配,当然你可以指定,后续的增减节点也可以重新分配。
输入yes开始创建
在这里插入图片描述
开启9001客户端 set aaa aaa
此时key:aaa 进行CRC16算法解析 再与16384求余 得到 slot[10439]
由上图可以看出9002的slot区间是 5461-10922 所以会重定向到9002服务器存储
在这里插入图片描述
get aaa 也是一样 key:aaa 得到slot[10439]
所以也是会重定向到9002服务器上读取
在这里插入图片描述

10.SpringBoot 整合redis集群:

spring:
  application:
    name: member
  redis:
    pool:
      max-idle: 100
      min-idle: 1
      max-active: 1000
      max-wait: -1
    timeout: 10000
    cluster:
      nodes:
        - 192.168.80.99:9001
        - 192.168.80.99:9002
        - 192.168.80.99:9003
        - 192.168.80.99:9004
        - 192.168.80.99:9005
        - 192.168.80.99:9006

11.缓存雪崩:

缓存雪崩,是指在某一个时间段,缓存集中过期失效
在这里插入图片描述在这里插入图片描述

Redis雪崩效应的解决方案
1、可以使用分布式锁 单机版的话本地锁
加锁这个只是减轻了数据库访问压力,一次一个造成阻塞,并不能提高吞吐量

2、消息中间件方式
如果大量的请求进行访问时候,Redis没有值的情况,通知消息中间件加载缓存(利用了MQ异步步特性)

3、一级和二级缓存 Redis+Ehchache

4、均摊分配Redis的key的失效时间(建议)
做电商项目的时候,一般是采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目的商品缓存时间长一些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源。
在这里插入图片描述

12.缓存穿透:

缓存穿透指的是,当请求过来缓存找不到对应的值,进而请求数据库,数据库也查询不到数据返回空,此时如果反复请求就会对数据库造成一定的压力
解决方法:在数据库找不到数据的时候,将空值存到缓存中,下一次同样的请求过来就可以找到对应的缓存值(只不过值为空),不用反复请求数据库
比如当前请求id:4 数据库暂时没有id:4的数据,不排除下一次新增的数据有会id:4的数据,所以在新增的同时必须清空id:4的缓存,再将数据存入缓存

public String getByUsers2(Long id) {
	// 1.先查询redis
	String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()[1].getMethodName()+ "-id:" + id;
	String userName = redisService.getString(key);
	if (!StringUtils.isEmpty(userName)) {
		return userName;
	}
	System.out.println("######开始发送数据库DB请求########");
	Users user = userMapper.getUser(id);
	String value = null;
	if (user == null) {
		// 标识为null
		value = SIGN_KEY;
	} else {
		value = user.getName();
	}
	redisService.setString(key, value);
	return value;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值