本篇主要是讲解原理
Redis官方网站
一、Redis 分片机制
1.1 原理说明
需求分析 : 单台redis节点,保存的数据是有限的.如果一味的增大单个节点的内存空间,不能从根本上解决内存不足的问题.如何实现有效的内存扩容呢?
采用多台redis服务器,共同维护一整块内存空间大小,最终实现了内存数据的扩容
1.2 redis分片搭建步骤(了解)
1.2.1 创建目录
在redis的根目录中创建shards文件夹 :
mkdir shards
1.2.2 复制配置文件
将redis.conf文件复制3份到shards中
cp redis.conf shards/redis-6379.conf
cp redis.conf shards/redis-6380.conf
cp redis.conf shards/redis-6381.conf
1.2.3 修改端口号
将port修改为对应的端口地址
vim redis-6379.conf
vim redis-6380.conf
vim redis-6381.conf
1.2.4 启动3台redis
1.启动3台redis:
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
2.查看rides服务,检查是否正常启动
ps -ef |grep redis
1.2.5 分片入门案例
测试redis分片
public class TestShards {
@Test
public void test01() {
String host = "192.168.56.129";
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(host, 6379));
shards.add(new JedisShardInfo(host, 6380));
shards.add(new JedisShardInfo(host, 6381));
ShardedJedis jedis = new ShardedJedis(shards);
jedis.set("1111", "学习redis分片机制");
System.out.println(jedis.get("1111"));
}
}
1.3 Spring整合redis分片
1.3.1 编辑pro配置文件
#redis分片写法
redis.nodes=192.168.56.129:6379,192.168.56.129:6380,192.168.56.129:6381
1.3.2 编辑配置类
实现spring容器管理redis配置类
@Configuration //标识配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.nodes}")
private String nodes;
/**
* redis分片
*/
@Bean
@Scope("prototype")
public ShardedJedis shardedJedis() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
String[] redisNodes = nodes.split(",");
for (String redisNode : redisNodes) {
String[] hostAndPort = redisNode.split(":");
String host = hostAndPort[0];
int port = Integer.parseInt(hostAndPort[1]);
JedisShardInfo info =
new JedisShardInfo(host, port);
shards.add(info);
}
return new ShardedJedis(shards);
}
}
1.3.3 编辑切面类信息
@Autowired
private shardedJedis jedis;
二、Hash一致性规则
2.1 Hash一致性算法介绍
- 确定节点node的位置
- 对key进行hash运算.获取唯一的位置
- 之后顺时针找到最近的节点
- 之后链接节点进行set/get操作
2.2 均衡性
说明 : 为了解决数据分配不均,采用虚拟节点的方式实现数据的均衡(均衡性算法)
问题说明 : 如果没有虚拟节点平衡数据,则会造成数据负载不均
2.3 单调性
说明 : 当节点新增时,数据可以实现自动的迁移
重点 : 一旦节点宕机,则内存缺失,整个分片不能正常使用
原则 : 如果节点新增,则尽可能保证原有的数据不发生变化
2.4 分散性
由于分布式的部署导致某些服务器不能使用全部的内存空间,同一个
key
有多个位置
2.5 负载
由于分布式的部署导致某些服务器不能使用全部的内存空间.同一个
位置
可能会有多个key
防止 : 尽可能使用全部的内存空间.能够有效的降低分散性和负载
2.6 总结
1、搭建缓存集群缓解服务器的访问压力
2、通过hash算法将数据合理的分配到每一台缓存服务器中。
3、出现增减缓存服务器是hash算法存在问题
4、引入一致性哈希算法解决这个问题-增减服务器时有一小部分数据受到影响
5、通过虚拟节点方式解决哈希偏斜问题
三、Redis持久化方式
Redis会根据配置文件的规则,定期将内存中的数据持久化到磁盘中.当redis重新启动时,会根据配置文件,实现内存数据的恢复
3.1 RDB模式
RDB模式是redis默认的持久化策略
特点:
- RDB模式定期实现数据的持久化 (可能会丢失数据)
. RDB模式记录的是内存数据的快照.持久化文件较小
. RDB模式在进行持久化操作时是阻塞的.(数据安全性考虑)
. 一般使用持久化的策略RDB的效率是最高的.建议使用
可以通过客户端执行
save
指令,实现内存数据的持久化操作
bgsave
表示后台运行,异步操作.
save
表示现在立即执行.表示同步操作.会造成线程阻塞
RDB的持久化策略:
save 900 1
如果用户在900秒内,执行1次更新操作时,则持久化一次
save 300 10
在300秒内,执行10次更新操作时,则持久化
save 60 10000
在60秒内,执行10000次更新操作时,则持久化
修改持久化文件名称的配置 :
redis.conf
3.3 AOF模式
AOF模式默认是关闭的.如果使用需要开启.AOF模式最的是数据的追加.所以持久化文件较大
特点:
- AOF模式默认是关闭的.
. AOF模式持久化时记录用户的操作过程,之后追加到持久化文件中
. AOF模式可以实现实时备份.保证数据安全
. AOF模式效率低于RDB模式
. AOF持久化文件需要定期维护
. AOF模式是异步的不会陷入阻塞
开启AOF模式 : 修改配置文件 :
redis.conf
AOF模式持久化策略:
appendfsync always 用户做一次操作,持久化一次
appendfsync everysec 每秒持久化一次
appendfsync no 由操作系统决定何时持久化. 一般不用
四、关于Redis内存策略
4.1 说明
Redis中自己有内存优化策略.能够保证在内存数据即将达到上限时,能够实现自动的优化. 但是该策略默认是关闭的
4.2 LRU算法
LRU(Least Recently Used) ,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
4.3 LFU算法
LFU(least frequently used),即最不经常使用页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
4.4 内存优化算法
内存优化策略 | 说明 |
---|---|
volatile-lru | 设定超时时间的数据采用LRU算法进行删除 |
allkeys-lru | 所有数据采用LRU算法进行删除 |
volatile-lfu | 设定超时时间的数据,采用LFU算法 |
allkeys-lfu | 所有数据采用LFU算法 |
volatile-random | 设定超时时间的随机算法 |
allkeys-random | 所有数据的随机算法 |
volatile-ttl | 设定超时时间的数据按照可存活时间排序删除 |
noeviction 默认设定 | 如果内存满了不会删除数据,而是报错返回,有使用这自行决定 |
4.5 修改内存策略
修改redis.conf文件 :
maxmemory-policy
五、Redis 哨兵机制(了解)
5.1 业务需求
redis分片实现了内存数据的扩容.但是redis分片没有实现高可用的效果.当redis分片的节点node如果宕机.导致整个分片不能正常执行.能否实现redis节点的高可用
5.2 Redis 主从复制
复制目录 : 将redis根目录中的shards目录复制为sentinel
cp -r shards sentinel
将redis配置文件复制好之后,将redis服务启动
检查节点状态
info replication
主从配置 : 让6370当主机,6380当从机 :
SLAVEOF 192.168.56.129:6379
(一旦实现主从结构之后,从机将不能set操作)
主从结构测试 : 检查是否可以通信
info replication
; 检查主从结构是否正常: 向redis主机中set数据,之后检查从机中是否实现数据同步
5.3 Redis哨兵实现
5.3.1 哨兵原理说明
实现步骤:
- 哨兵启动时首先监控主机的状态,并且记录主机的全部信息(包括从机的host:port)
. 当主机发生宕机现象时.首先会根据PING-PONG心跳检测机制,查看主机的状态,如果连续3次主机无法响应,则断定主机宕机
. 由哨兵利用自己的推选的算法.选举出新的主机.并且将其他的节点改为当前主机的从机.
5.3.2 编辑哨兵配制文件
将哨兵的配置文件复制到sentinel目录中
关闭哨兵保护模式 : 配置文件中找到
pritected-mode
改为no
开启后台启动 : 配置文件中找到
daemonize
改为yes
修改哨兵监控信息 :
mymaster:变量名称 ;标识主机信息1 : 哨兵选举的票数; 一般数量> 哨兵 1/2
修改宕机的超时时间
启动哨兵 :
redis-sentinel sentinel.conf
5.3.3 关于redis高可用问题
- 前提:必须配置主从结构
- 如果出现了哨兵不能正确选举.则需要重新配置主从
- 解决方案:编辑redis.conf的配置文件,之后删除最后一行信息.删除之后重新挂载.
5.4 Spring整合Redis哨兵
5.4.1 入门案例
端口说明:
默认端口: 6379
通信端口:16379 PING-PONG
哨兵端口:26379
public class TestSentinel {
/**
* 程序链接哨兵入门案例
* masterName:mymaster
* sentinels: 哨兵的Set集合信息.
*/
@Test
public void test01() {
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.56.129:26379");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
Jedis jedis = pool.getResource();
jedis.set("1907", "redis哨兵测试成功!!!!");
System.out.println(jedis.get("1907"));
}
}
5.4.2 编辑pro文件
#redis哨兵配置
redis.sentinels=192.168.175.129:26379
5.4.2 编辑配置类
实现spring容器管理redis配置类
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.sentinels}")
private String sentinels;
/*实现哨兵的配置*/
@Bean //定义哨兵池对象
public JedisSentinelPool pool() {
Set<String> set = new HashSet<>();
set.add(sentinels);
return new JedisSentinelPool("mymaster",set);
}
//规则:可以为bean的方法自动的注入参数对象
@Bean
@Scope("prototype")
public Jedis jedis(JedisSentinelPool pool) {
return pool.getResource();
}
}
随手笔记
1.关于redis高可用问题
- 前提:必须配置主从结构.
- 如果出现了哨兵不能正确选举.则需要重新配置主从
- 解决方案 : 编辑
redis.conf
的配置文件,之后删除最后一行信息.删除之后重新挂载
2.关于RDB和AOF的说明
1.是否允许数据丢失 ? RDB(yes) ; AOF(no)
2.是否允许2种模式同时存在?
允许,一般在主从结构中使用.主节点选用dB模式,从节点选用AOF模式.如果出现特殊现象,则可直接拷贝AOF文件/RDB文件实现数据恢复
3.效率问题RDB高于AOF
4.RDB做内存数据的快照,AOF记录用户的操作过程.
5.RDB同步操作AOF模式异步操作