Redis内存策略
- LRU算法:(Least Recently Used)最近最少使用。自上一次使用时间T,并且挑选最大的T进行删除。 算法维度是时间T。
- LFU算法:(Least Frequently Used)最不经常使用。这是Redis5.0以后才引用的。算法维度是引用次数。
内存策略配置:
- volatile-lru:设定了超时时间的数据,采用LRU算法进行删除
- allkeys-lru:全部数据采用LRU算法进行删除
- volatile-lfu:设定了超时时间的数据采用LFU算法删除
- allkeys-lfu:所有数据采用LFU算法删除数据
- volatile-random:设定了超时的时间的数据采用随机算法删除
- allkeys-random:所有数据采用随机算法进行删除
- volatile-ttl:为数据添加了超时时间的并且马上就要超时的数据提前删除
- noeviction:(默认配置)如果内存溢出时,不会自动删除数据。只会报错返回给用户。有些数据很重要,redis不能盲目删除。
可在配置文件的597行修改内存策略:
第597行进行修改如果有需要
Redis持久化策略
说明:Redis服务器会将内存数据定期持久化到磁盘中。当redis服务器宕机时,下次重启服务器时首先根据配置文件中的持久化方式进行数据的恢复。
- RDB模式:
Ⅰ. RDB模式是redis中的默认持久化方式
Ⅱ. RDB模式记录的是内存数据的快照,记录内存状态。每次都保存最新的数据
Ⅲ. RDB模式的持久化效率是最高的
Ⅳ. RDB模式持久化操作可能会让程序陷入阻塞(命令1:save 陷入阻塞、命令2:bgsave 后台运行不会陷入阻塞)
Ⅴ. RDB模式工作时,定期(每隔一段时间)持久化,隐患:可能会丢失数据 - AOF模式:
Ⅰ. AOF模式可以保证数据的实时持久化操作
Ⅱ. AOF模式默认是关闭的,需要手动开启(配置文件698行改为appendonly yes)
Ⅲ. AOF模式记录的是用户的操作过程
Ⅳ. AOF文件特别庞大,需定期维护
如果数据允许少量丢失则首选RDB模式。如果内存数据不允许丢失,则使用AOF ,需要定位维护持久化文件大小。
Redis集群
通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取。Redis是一个很好的Cache工具。大型网站应用,热点数据量往往巨大,几十G上百G是很正常的。由于内存大小的限制,使用一台Redis实例显然无法满足需求,这时就需要使用多台Redis 作为缓存数据库。但是如何保证数据存储的一致性呢,这时就需要搭建Redis集群。采用合理的机制,保证用户的正常的访问需求。采用Redis集群,可以保证数据分散存储,同时保证数据存储的一致性。并且在内部实现高可用的机制。实现了服务故障的自动迁移。
- 集群搭建计划
主从划分:3台主机3台从机,共6台
端口划分:7000到7005 - 前期准备
-
确保没有redis服务器启动
- 准备集群目录,在redis根目录下执行mkdir cluster
- 在cluster目录下分别创建7000-7005目录
- 将redis根目录中的redis.conf文件复制到cluster/7000/并以原名保存
- 修改/usr/local/src/redis/cluster/7000下刚复制的redis.conf
-
- 注释本地绑定IP地址
- 注释本地绑定IP地址
-
- 关闭保护模式
- 关闭保护模式
-
- 修改端口号
- 修改端口号
-
- 开启后台启动
- 开启后台启动
-
- 修改pid文件(在7000目录下专门形成自己各自的pid文件)
- 修改pid文件(在7000目录下专门形成自己各自的pid文件)
-
- 修改持久化文件路径
- 修改持久化文件路径
-
- 设定内存优化策略
- 设定内存优化策略
-
- 关闭AOF模式
- 关闭AOF模式
-
- 开启集群配置
- 开启集群配置
-
- 开启集群配置文件
- 开启集群配置文件
-
- 修改集群超时时间
分别复制7000目录下修改好的redis.conf文件到7001、7002、7003、7004、7005目录
- 修改集群超时时间
- 分别将7001- 7005目录下redis.conf中的7000改为对应的端号的名称
- 通过脚本编辑启动/关闭指令
-
1.创建启动脚本 vim start.sh
编辑start.sh内容为如下图:
启动命令
-
2.创建关闭脚本 vim stop.sh
编辑stop.sh内容为如下图:
关闭命令
- 创建redis集群
先执行sh start.sh,让所有redis都运行,再复制粘贴下面这段代码运行
#需要搭建时先把这段代码中的192.168.80.128地址替换成自己的linux ip地址再进行复制
redis-cli --cluster create --cluster-replicas 1 192.168.80.128:7000 192.168.80.128:7001 192.168.80.128:7002 192.168.80.128:7003 192.168.80.128:7004 192.168.80.128:7005
回车后:
Redis集群搭建出错解决方法
搭建redis集群时,节点中的数据必须为null
- 关闭redis所有服务器:sh stop.sh
- 删除7000-7005这六个目录下的除了redis.conf之外的所有文件
- 重启所有的redis:sh start.sh
- 再复制粘贴下面这段代码运行
#需要搭建时先把这段代码中的192.168.80.128地址替换成自己的linux ip地址再进行复制
redis-cli --cluster create --cluster-replicas 1 192.168.80.128:7000 192.168.80.128:7001 192.168.80.128:7002 192.168.80.128:7003 192.168.80.128:7004 192.168.80.128:7005
Redis集群高可用推选原理
Redis的所有节点都会保存当前Redis集群中的全部主从状态信息。并且每个节点都能够相互通信。当一个节点发生宕机现象,则集群中的其他节点通过PING - PONG检测机制检查Redis 节点是否宕机。当有半数以上的节点认为宕机,则认为主节点宕机。同时由Redis剩余的主节点进入选举机制,投票
选举链接宕机的主节点的从机为新主机,实现故障迁移。
单元测试Redis集群AIP
/**
* 实例化集群对象
*/
@Test
public void testCluster() {
Set<HostAndPort> nodes=new HashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.80.128", 7000));
nodes.add(new HostAndPort("192.168.80.128", 7001));
nodes.add(new HostAndPort("192.168.80.128", 7002));
nodes.add(new HostAndPort("192.168.80.128", 7003));
nodes.add(new HostAndPort("192.168.80.128", 7004));
nodes.add(new HostAndPort("192.168.80.128", 7005));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("1901", "redis集群操作ok");
System.out.println(cluster.get("1901"));
}
springBoot整合Redis集群
配置文件:properties/redis.properties
#配置redis主机信息 单台
#redis.node=192.168.80.128:6379
#
##配置redis分片机制 多台
#redis.shards=192.168.80.128:6379,192.168.80.128:6380,192.168.80.128:6381
#
##配置redis哨兵
#redis.sentinel=192.168.80.128:26379
#配置集群
redis.clusters=192.168.64.128:7000,192.168.64.128:7001,192.168.64.128:7002,192.168.64.128:7003,192.168.64.128:7004,192.168.64.128:7005
创建配置类RedisConfig
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
/**
* springboot整合redis集群
*/
@Value("${redis.clusters}")
private String jedisCluster;
@Bean
@Scope("prototype")
public JedisCluster jedisCluster() {
Set<HostAndPort> setNodes=new HashSet<>();
String[] nodes = jedisCluster.split(",");
for (String node : nodes) {
String ip=node.split(":")[0];
Integer port = Integer.valueOf(node.split(":")[1]);
HostAndPort hostAndPort = new HostAndPort(ip, port);
setNodes.add(hostAndPort);
}
return new JedisCluster(setNodes);
}
}