亿级并发|day10-Redis进阶

1 Redis持久化策略

1.1 策略说明

说明:
redis作为内存数据库,需要保持大量用户的数据。但是redis中的数据保存在内存中,一旦遇上断电/宕机,肯定会导致内存数据丢失。
所以为了防止数据丢失,redis采用持久化的方式,实现内存数据的备份。

策略说明:
当redis内存中有数据时,自身支持两种策略模式:

  • RDB模式
  • AOF模式

redis根据相应模式的设置进行数据持久化,且RDB模式和AOF模式都有各自的持久化文件。当redis重启时,redis会根据配置文件中指定的持久化文件名称,加载持久化文件,为内存恢复数据。

1.2 RDB模式

1.2.1 模式说明

RDB模式定期将内存中的数据持久化。
如果用户允许丢失少量的数据则首选RDB模式,因为RDB模式定期为内存做快照,该方式的备份速度很快。

1.2.2 备份命令

**说明:**执行redis备份命令需要在redis客户端执行。

命令:
手动保存

save

后台备份

bgsave

区别:
save 会造成线程阻塞,只有当备份完成时,才允许执行redis更新操作。
bgsave 表示后台运行,不会造成线程阻塞,挑当前不忙的时间做数据备份。

在这里插入图片描述

1.2.3 备份方式

save 900 1

在900秒内,redis做一次更新操作,则备份一次

save 300 10

在300秒内,redis做10次更新操作,则备份一次

save 60 10000

在60秒内,如果redis做10000次操作则备份一次

1.2.4 配置文件说明

1.持久化文件名称
在这里插入图片描述

2.持久化文件保存路径

dir ./

表示当前文件夹,建议使用绝对路径。

1.3 AOF模式

1.3.1 模式说明

AOF模式可以做到实时数据备份,该模式相当于用配置文件记录了用户的全部操作过程。

特点:

  • 可以实时备份数据,安全性好
  • 持久化速度较RDB模式更慢
  • AOF模式的持久化文件的体积会很大
  • 当数据恢复时,需要消耗很长时间
  • 持久化文件明文保存,没有加密

1.3.2 AOF模式持久化策略

1.开启AOF模式
注意:开启AOF模式后,RDB模式不生效。
在这里插入图片描述

2.AOF模式持久化文件保存路径

dir ./

3.持久化策略

# appendfsync always    每次操作都会备份
appendfsync everysec    每秒备份一次
# appendfsync no         不做操作

2 Redis内存策略

2.1 需求分析

question:
为了保证服务器正常运行,需要为redis设定最大内存空间,但是如果数据一直新增,内存很快就会占满,如何优化内存?

解决方案:
采用LRU算法,将内存中最近最不常用的数据清空,保存其他数据。

2.2 内存优化手段

1.设定内存空间
建议内存不要超过1G,通常256~512M足矣。

修改redis配置文件第537行
在这里插入图片描述

2.设定合适的内存策略
可选的内存策略:

  • volatile-lru
    在已经设定超时时间的数据中,采用LRU算法进行删除。

  • allkeys-lru
    在所有key中,采用LRU算法进行删除。

  • volatile-random
    在已经设定超时时间的数据中,随机删除。

  • allkeys-radom
    在所有key中,随机删除

  • volatile-ttl
    在已经设定超时时间的数据中,根据TTL机制排序,将马上要过期的数据删除。

  • noviction
    如果采用该机制,那么内存数据不会删除,将报错消息返回给用户。

策略设定:
在这里插入图片描述

2.3 缓存使用问题

1.缓存穿透

条件:访问一条不存在的数据

说明:当访问一个不存在的数据时,因为缓存中没有这个key,导致缓存形同虚设,最终访问后台数据库,但数据库中也没有该数据所以返回null。

隐患:如果有人恶意频繁查询一个不存在的数据,可能会导致数据库负载过高而宕机。

总结:业务系统访问一个不存在的数据,称之为缓存穿透。

防护:限定同一IP访问频率,如京东。

2.缓存击穿

条件:当一条缓存失效/过期/未命中时,高并发访问该key

说明:如果给一个key设置了失效时间,当key失效时有一万的并发请求访问这个key,此时缓存失效,所有的请求都会访问后台数据库,称之为缓存击穿。

场景:微博热点消息访问量很大,如果该缓存失效则会直接访问后台数据库,导致后台数据库负载过高。

3.缓存雪崩

前提:高并发访问,缓存命中较低或者失效时。

说明:假设缓存都设置了失效时间,在同一时间内缓存大量失效,如果这时用户高并发访问,缓存命中率过低,导致全部的用户访问都会访问后台真实的数据库。

场景:在高并发情况下,缓存动态更新时。

3 Redis分片技术

3.1 需求分析

1.如果将全部数据都保存到一台tomcat中,如果该服务器损坏,则将影响全部服务。
2.使用单台redis内存设定一般不要超过1G,但有些业务数据量很大,如果不修改内存则无法存储。

3.2 改进方案

方案:采用Redis分片技术实现。

优点:

  • 使用redis分片可以实现内存数据的动态扩容。
  • 使用分片,每台redis节点中尽可能存放1/n的数据,防止数据丢失。
  • 对于用户而言,整个redis分片就是一个服务。

3.3 分片搭建

3.3.1 复制配置文件

说明:将redis.conf文件复制到shards中,并且复制3份名称为:

  • redis-6379.conf
  • redis-6380.conf
  • redis-6381.conf

在这里插入图片描述

3.3.2 修改端口号

说明:分别修改6380/6381的配置文件为对应端口
在这里插入图片描述

3.3.3 重启Redis服务

在这里插入图片描述

3.3.4 分片测试

@Test
public void testShard(){

	/**
	 * 创建分片的对象
	 * 1.poolConfig  标识池的大小
	 * 2.shards redis分片的节点信息
	 */
	
	JedisPoolConfig poolConfig = new JedisPoolConfig();
	poolConfig.setMaxTotal(1000);
	poolConfig.setTestOnBorrow(true); //获取链接时先检测
	
	List<JedisShardInfo> shards = new ArrayList<>();
	shards.add(new JedisShardInfo("192.168.126.166",6379));
	shards.add(new JedisShardInfo("192.168.126.166",6380));
	shards.add(new JedisShardInfo("192.168.126.166",6381));
	
	ShardedJedisPool pool = 
	new ShardedJedisPool(poolConfig, shards);
	
	//获取redis链接
	ShardedJedis jedis = pool.getResource();
	
	jedis.set("shards","保存分片数据");
	System.out.println(jedis.get("shards"));
	//将链接还回池中
	pool.returnResource(jedis);
}

3.4 Hash一致性算法

3.4.1 数据如何保存

在这里插入图片描述

1.利用节点的IP+算法确定唯一的哈希值,之后在内存中确定节点的位置。
2.当保存数据时,根据key进行hash运算,确定唯一的一个位置。
3.根据当前key位置顺时针查找最近的node节点进行挂载。

3.4.2 均衡性

说明:根据redis节点的数量尽可能让数据均匀地分片,每个节点中的数据尽可能趋向1/n。

提升:为了保证均衡性,哈希一致性算法引入了虚拟节点的概念。为了平衡数据,如果一个节点不够则生成多个节点。
在这里插入图片描述

3.4.3 单调性

说明:如果node节点的新增,能动态地实现数据的迁移,这种特性被称之为单调性。
在这里插入图片描述

3.4.4 分散性

特点:由于分布式的原因,用户在使用内存时,不能够获取全部的内存空间,导致一个key对应多个位置。
在这里插入图片描述

3.4.5 负载

说明:负载是从另一个角度考虑分散性。

特点:一个位置对应多个key
在这里插入图片描述

如何解决:在进行架构设计时,要求使用全部的内存空间。

4 Spring整合分片

4.1 编辑pro文件

redis.host=192.168.126.166
redis.port.a=6379
redis.port.b=6380
redis.port.c=6381
redis.maxTotal=1000

4.2 编辑Spring配置文件

<!--实现spring整合分片  -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxTotal" value="${redis.maxTotal}"/>
</bean>

<!--定义三个redis节点  -->
<bean id="shardInfoA" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.a}"/>
</bean>

<bean id="shardInfoB" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.b}"/>
</bean>

<bean id="shardInfoC" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.c}"/>
</bean>

<!--定义连接池  -->
<bean id="jedisPool" class="redis.clients.jedis.ShardedJedisPool">
	<constructor-arg name="poolConfig" ref="poolConfig"/>
	<constructor-arg name="shards">
		<list>
			<ref bean="shardInfoA"/>
			<ref bean="shardInfoB"/>
			<ref bean="shardInfoC"/>
		</list>
	</constructor-arg>
</bean>

4.3 编辑工具API

@Service
public class RedisService {

	//有的工程需要,有的工程不需要。设置required=false,有就注入,没有就不注入。
    @Autowired(required = false)
    private ShardedJedisPool shardedJedisPool;

    
    public void set(String key,String value){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	
    	jedis.set(key, value);
    	shardedJedisPool.returnResource(jedis);
    }
    
    //添加超时时间
    public void set(String key,String value,int seconds){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	
    	jedis.setex(key, seconds, value);
    	shardedJedisPool.returnResource(jedis);
    }
    
    //编辑get方法
    public String get(String key){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	String result = jedis.get(key);
    	shardedJedisPool.returnResource(jedis);
    	return result;
    }
}

4.4 编辑业务层方法

1.修改自动注入对象
在这里插入图片描述

2.切换业务方法
在这里插入图片描述

5 Redis哨兵

5.1 业务需求

采用redis分片技术可以实现内存扩容,但是如果其中一台机器宕机,则整个redis分片将不能正常运行。

5.2 实现主从挂载

角色划分:
6379(主机)
6380(从机)
6381(从机)

1.检查节点状态
命令:

info replication

在这里插入图片描述

2.实现主从挂载
命令:

127.0.0.1:6380> SLAVEOF 192.168.126.166 6379

3.检查状态
在这里插入图片描述

5.3 哨兵实现

5.3.1 哨兵原理

在这里插入图片描述

  • 哨兵监控主机的状态,并获取主机的全部信息,包括从机的信息。
  • 通过心跳检测机制,如果3次连接没有响应,则断定主机宕机了。此时哨兵会从从机中选举一台从机充当从机,同时将另外的从机挂载到现在的主机。
  • 当旧的主机修复完成后,继续充当从机,等待下次选举。

5.3.2 编辑哨兵配置文件

1.以原名保存文件

cp sentinel.conf sentinel

2.关闭保护模式
在这里插入图片描述

3.修改哨兵监听节点信息

sentinel master mymaster 127.0.0.1 1

说明
mymaster 表示主机变量名称
IP:端口 表示主机信息
2 表示选举票数
在这里插入图片描述

4.修改推选时间
在这里插入图片描述

5.修改推选失败时间
在这里插入图片描述

5.3.3 哨兵测试

1.启动哨兵

redis-sentinel sentinel.conf

2.启动测试
在这里插入图片描述

3.关闭主机,检查哨兵能否推选
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/s15810813994/article/details/83108547
今日推荐