redis(2)
redis分片
采用多台redis服务器,共同维护一整块内存空间大小,最终实现了内存数据的扩容.
1.在redis的根目录中创建shards文件夹 mkdir shards
2.将redis.conf文件复制3分到shards中 cp redis.conf shards
3.修改端口号 vim redis.conf
4.启动3台redis
Hash一致性规则
1.Hash一致算法介绍
1)确定节点node的位置.
2)对key进行hash运算.获取唯一的位置
3)之后顺时针找到最近的节点.
4)之后链接节点进行set/get操作.
2.均衡性
为了解决数据分配不均,采用虚拟节点的方式实现数据的均衡(均衡性算法)
3.单调性
当节点新增时,数据可以实现自动的迁移.
重点:一旦节点宕机,则内存缺失.整个分片不能正常使用.
原则:如果节点新增,则尽可能保证原有的数据不发生变化.
4.分散性
由于分布式的部署导致某些服务器不能使用全部的内存空间,同一个key有多个位置
5.负载
由于分布式的部署导致某些服务器不能使用全部的内存空间.同一个位置可能会有多个key
防止:尽可能使用全部的内存空间.能够有效的降低分散性和负载.
Spring管理Redis分片
1.编辑properties配置文件
#redis分片写法
redis.nodes=192.168.175.129:6379,192.168.175.129:6380,192.168.175.129:6381
2.编辑配置类
/**
* 实现spring容器管理redis配置类
* @author Administrator
*
*/
@Configuration //标识配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.nodes}")
private String nodes; //node,node,node
/**
* redis分片
*/
@Bean
@Scope("prototype")
public ShardedJedis shardedJedis() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
String[] redisNodes = nodes.split(",");
for (String redisNode : redisNodes) {
//redisNode=IP:PORT
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);
}
}
3.编辑切面信息
@Component //将类交给容器管理
@Aspect //标识切面
public class CacheAspect {
@Autowired
//private Jedis jedis;
private SharedJedis jedis;
//如果是环绕通知,则参数必须写ProceedingJoinPoint,必须位于第一位
@Around("@annotation(cacheFind)")
............
redis持久化方式
Redis会根据配置文件的规则,定期将内存中的数据持久化到磁盘中.当redis重新启动时,会根据配置文件.实现内存数据的恢复
一、RDB模式
RDB模式是redis默认的持久化策略.
1.特点:
1).RDB模式定期实现数据的持久化 (可能会丢失数据)
2).RDB模式记录的是内存数据的快照.持久化文件较小.
3).RDB模式在进行持久化操作时是阻塞的.(数据安全性考虑)
4).一般使用持久化的策略RDB的效率是最高的.建议使用.
2.save指令(save、bgsave)
可以通过客户端执行save指令.实现内存数据的持久化操作
bgsave表示后台运行,异步操作.
save表示现在立即执行.表示同步操作.会造成线程阻塞.
3.持久化配置名称
4.RBD持久化策略
save 900 1 如果用户在900秒内,执行1次更新操作时,则持久化一次
save 300 10 在300秒内,执行10次更新操作时,则持久化
save 60 10000在60秒内,执行10000次更新操作时,则持久化
save 1 1 效率极低.
二、 AOF模式
AOF模式默认是关闭的.如果使用需要开启.AOF模式最的是数据的追加.所以持久化文件较大.
1.特点:
1).AOF模式默认是关闭的.
2).AOF模式持久化时记录用户的操作过程,之后追加到持久化文件中.
3).AOF模式可以实现实时备份.保证数据安全.
4).AOF模式效率低于RDB模式
5).AOF持久化文件需要定期维护.
6).AOF模式是异步的不会陷入阻塞
2.AOF持久化策略
appendfsync always 用户做一次操作,持久化一次
appendfsync everysec 每秒持久化一次(默认)
appendfsync no 由操作系统决定何时持久化. 一般不用
Redis内存策略
Redis中自己有内存优化策略.能够保证在内存数据即将达到上限时,能够实现自动的优化. 但是该策略默认是关闭的.
1.LRU算法
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面内置算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面
自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
2.LFU算法
LFU(least frequently used (LFU) page-replacement algorithm)。即最不经常使用页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用
次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
3.内存优化算法
1).volatile-lru 设定超时时间的数据采用lru算法进行删除
2).allkeys-lru 所有数据采用LRU算法进行删除.
LFU redis5.0版本以后的算法.
3).volatile-lfu 设定超时时间的数据,采用lfu算法
4).allkeys-lfu 所有数据采用lfu算法.
5).volatile-random 设定超时时间的随机算法
6).allkeys-random 所有数据的随机算法
7).volatile-ttl 设定超时时间的数据按照可存活时间排序删除
8).noeviction 默认设定 如果内存满了不会删除数据,而是报错返回,有使用这自行决定.
4.修改内存
Redis哨兵机制
redis分片实现了内存数据的扩容.但是redis分片没有实现高可用的效果.当redis分片的节点node如果宕机.导致整个分片不能正常执行.能否实现redis节点的高可用.
1.redis主从复制
1.1复制目录
将redis根目录中的shards目录复制为sentinel cp -r shards sentinel
1.2检查节点状态
默认状态下,redis节点都是主机
1.3主从配置
注意:一旦实现主从结构之后,从机将不能set操作
1.4主从结构测试
1)在主机客户端使用 info replication 命令
2)向redis主机中set数据,之后检查从机中是否实现数据同步
1.5.redis哨兵实现
实现步骤:
1)哨兵启动时首先监控主机的状态,并且记录主机的全部信息(包括从机的host:port);
2)当主机发生宕机现象时.首先会根据PING-PONG心跳检测机制,查看主机的状态,如果连续3次主机无法响应,则断定主机宕机.
3)由哨兵利用自己的推选的算法.选举出新的主机.并且将其他的节点改为当前主机的从机.
1.6 编辑哨兵配制文件
1)将哨兵的配置文件复制到sentinel目录中.
2)关闭哨兵保护模式
3)开启后台启动
4)修改哨兵监控信息
mymaster:变量名称 标识主机信息
1: 哨兵选举的票数. 一般数量> 哨兵 1/2
5)修改宕机的超时时间
6)启动哨兵 redis-sentinel sentinel.conf
注意:配置哨兵前必须配置主从结构
Spring整合哨兵
1.编辑properties文件
#redis哨兵配置
redis.sentinels=192.168.175.129:26379
2.编辑配置类
@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的方法自动的注入参数对象
//方法2:指定ID进行注入
//@Qualifier("jedisSentinelPool")JedisSentinelPool pool
@Bean
@Scope("prototype")
public Jedis jedis(JedisSentinelPool pool) {
return pool.getResource();
}
}
3.编辑切面
@Component //将类交给容器管理
@Aspect //标识切面
public class CacheAspect {
@Autowired
private Jedis jedis;
//private SharedJedis jedis;
//如果是环绕通知,则参数必须写ProceedingJoinPoint,必须位于第一位
@Around("@annotation(cacheFind)")
............