Redis集群
一 Reids 简单优化
1 配置优化
-
最大连接数
maxclients 10000
-
内存优化。Redis 的所有数据都存放在内存中,因此需要注意内存的使用和管理。可以设置 Redis 的 maxmemory 和 maxmemory-policy 等参数来控制 Redis 的使用内存量。另外,可以使用 Redis 的 LRU 算法来限制过期数据的存储。 默认是0就是不限制,一般设置3/4; 过期策略默认是不淘汰(根据自己项目来)
-
使用持久化。Redis 支持 RDB 和 AOF 两种持久化方式,可以选择适合自己业务场景的持久化方式。RDB 持久化方式会周期性地将 Redis 数据集快照写入磁盘,而 AOF 持久化方式则记录每个写操作,并在 Redis 启动时重新执行这些操作来恢复数据。 都要开启
-
安全配置
设置访问密码,bind安全访问配置
2 代码优化
-
避免过度使用键。Redis 中的键是非常快速的查找方式,而过度使用键可能会导致 Redis 性能下降。因此,应该考虑将相关数据放在同一个键下进行存储,并确保键名简洁明了。
键不能太多
不能太长
**命名规范-*不要使用空格, %…
-
优化 Lua 脚本。Redis 可以通过执行 Lua 脚本来将多个命令组合成一条原子操作。但是,Lua 脚本应该尽量简单和高效,以避免占用过多的资源
-
使用 Pipeline。Redis 的 Pipeline 可以将多条操作命令打包发送给服务器,从而减少网络通信开销和等待时间,提高效率。
/** * pipline批量查询获取key * @param keys * @return 存在的key,value 映射map */ public static Map<String, String> getByPipeline(List<String> keys) { Map<String, String> result = new HashMap<>(); try (Jedis jedis = RedisClient.getJedis()) { Pipeline pipeline = jedis.pipelined(); Map<String, Response<String>> responses = new HashMap<String,Response<String>>(keys.size()); for(String key : keys) { responses.put(key, pipeline.get(key)); } pipeline.sync(); responses.forEach((key, response) ->{ if(StringUtils.isNotEmpty(response.get())){ result.put(key, response.get()); } }); return result; } }
3 集群优化
redis为什么这么快?? 单机支持10W左右并发
1 操作内存
2 使用单线程,避免了线程切换和竞争锁产生损耗
3 基于非阻塞IO多路复用机制
4 基于c语言实现,并且还做大量优化,效率很高
集群化部署。Redis 可以通过 cluster 模式进行集群化部署,从而提高 Redis 的吞吐量和可用性。集群部署时,需要注意均衡负载和节点间的数据同步。
二.Redis集群理解
1.Redis集群方案
1.1.Redis为什么做集群
- 单点故障问题
- 高并发
- 海量数据
1.2.Redis主从复制 主–从(多个)
单点没有解决 (单主)
高并发解决了(读写分离)
海量数据没有解决(每个服务器都是一样的数据)
1.什么是主从复制
Redis有三种集群方案,主从复制,哨兵,cluster集群,主从复制是指将一台Redis服务器的数据,复制到其他的Redis服务器
。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
图解Redis主从: 主从同步(redis自己功能)、读写分离、主备切换
2.主从原理
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
- 从服务器连接主服务器,发送SYNC命令;
- 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
- 主服务器BGSAVE执行完后,向所有从服务器发送快照文件(rdb文件),并在发送期间继续记录被执行的写命令;
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
- 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
Redis增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
3.主从复制的作用
数据冗余
:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复
:当主节点出现问题时可以由从节点提供服务实现快速的故障恢复;实际上是一种服务的冗余
负载均衡
:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
读写分离
:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量。
高可用基石
:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
4.主从的缺点
不具备自动容错和恢复功能
:主从宕机会影响前端的部分请求失败,需要重启机器或者手动切换前端IP才能恢复
主机宕机数据丢失
:宕机前部分有部分数据未同步到从机,切换IP后会引入数据不一致降低系统可用性
数据大的问题
:数据量特别大一个主是存储不了
数据库中同步数据canal和kettle等工具就支持全量和增量!!!
2.3.Redis哨兵模式(数据量不是太大情况下,并且读多写少)
- 单点故障问题 解决
- 高并发 解决
- 海量数据 没有解决
https://cloud.tencent.com/developer/article/1409270
1.什么是哨兵模式(Redis-Sentinel)
当主服务器中断服务后,可以将一个从服务器升级为主服务器
,以便继续提供服务,但是这个过程需要人工手动来操作。 为此,Redis 2.8中提供了哨兵工具来实现自动化的系统监控和故障恢复功能。
Redis-Sentinel是用于管理Redis集群,该系统执行以下三个任务
监控(Monitoring)
Sentinel会不断地检查你的主服务器和从服务器是否运作正常;
提醒(Notification)
当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知;
自动故障迁移(Automatic failover)
当主服务器不可用,Sentinel会自动选举一个从服务器作为新的主服务器,并让其它的从服务器从新的主服务器复制数据,用户的请求会被变更为新的主服务器。
2.图解Redis哨兵
- 主观下线&客观下线&故障转移
主观下线
每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线
(SDOWN)
如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
客观下线
当有足够数量(半数以上)的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线
(ODOWN)
若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。
故障转移
当前哨兵发现了主服务器客观下线,需要故障恢复,故障恢复需要由领头哨兵来完成。这样来保证同一时间只有一个哨兵来执行故障恢复,选出领头哨兵后,领头哨兵将会开始对主数据库进行故障恢复。
首先是从主服务器的从服务器中选出一个从服务器作为新的主服务器。选出之后通过slaveif no ont将该从服务器升为新主服务器。
所有在线的从数据库中,选择优先级最高的从数据库。优先级通过replica-priority参数设置,优先级相同,则复制的命令偏移量越大(复制越完整)越优先 , 如果以上都一样,则选择运行ID较小的从数据库
选出一个从数据库后,领头哨兵将向从数据库发送SLAVEOF NO ONE命令使其升格为主数据库,而后领头哨兵向其他从数据库发送 SLAVEOF命令来使其成为新主数据库的从数据库,最后一步则是更新内部的记录,将已经停止服务的旧的主数据库更新为新的主数据库的从数据库,使得当其恢复服务时自动以从数据库的身份继续服务。
- 哨兵的优缺点
哨兵的优点
哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。主从可以自动切换,系统更健壮,可用性更高。
哨兵的缺点
主从服务器的数据要经常进行主从复制,这样造成性能下降。当主服务器宕机后,从服务器切换成主服务器的那段时间,服务是不能用的。
有可能少量损失数据!!! ???
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂
不支持海量数据
2.4.Redis-Cluster集群
单点故障: 主从
高并发: key不同,有可能到不同主从里面去,主从还能做读写分离
海量数据: 每个主数据都是不一样,多个主就能存更多数据.
- 为什么要Redis-Cluster
redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容
。
- 什么是Redis-Cluster
Redis-Cluster采用无中心结构,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接
,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据
。
- 数据分散存储
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)
的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16(一种hash算法)
算法来取模得到所属的slot
,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384
。
- 容错机制-投票
为了防止主节点数据丢失,可以为每个主节点可以准备特定数目的备节点,主节点挂掉从节点可以升级为主节点(类哨兵模式) 。
容错机制指的是,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作. 故障节点对应的从节点自动升级为主节点 , 如果某个主挂掉,而没有从节点可以使用,那么整个Redis集群进入宕机状态 要通过raft算法来选举新主,常见选举算法
三.Redis集群搭建
1.环境准备
1.1.Redis 3.2
-
需要 6 台 redis 服务器。。
-
6 台 redis 服务器需要运行在不同的端口 6379-6384 搭建伪集群
1.2.Ruby语言运行环境
我们需要使用ruby脚本来实现集群搭建
-
Ruby 打包系统RubyGems java->maven
RubyGems简称gems,是一个用于对 Ruby组件进行打包的 Ruby 打包系统
-
Redis的Ruby驱动redis-xxxx.gem—pom(arifyid,)
-
创建Redis集群的工具ruby redis-trib.rb java xxx.class
ruby -java
gems–maven
redis.xxx.gem–pom(坐标)
ruby redis-trib.rb java xxx.class
2.Redis集群安装
2.1.安装6台Redis
- 在Window搭建6个伪集群每个Redis创建启动脚本start.bat,内容如下
title redis-3679
redis-server.exe redis.windows.conf
2.2.Redis配置
-
修改redis.windows.conf,端口号分别对应:
6379、6380、6381、6382、6383、6384。
-
开启cluster-enabled :
cluster-enabled yes
-
指定集群配置文件:
cluster-config-file nodes-6379.conf
,cluster-config-file nodes-6379.conf 是为该节点的配置信息,这里使用 nodes-端口.conf命名方法。服务启动后会在目录生成该文件。 -
指定超时:
cluster-node-timeout 15000
-
开启持久:
appendonly yes
2.3.安装Ruby
rubyinstaller-2.6.3-1-x64.exe 傻瓜式安装即可
2.4.安装Ruby驱动-打包软件
- 解压Ruby驱动(rubygems-2.7.7) , 进入根目录,执行
ruby setup.rb
- 切入到Redis目录执行(6379的Redis目录) gem install redis
2.5.执行集群构建脚本
-
启动6个Redis
-
拷贝redis-trib.rb到Redis目录(6379的Redis目录)
-
在6379根目录执行构建脚本:
redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
- 在出现 Can I set the above configuration? (type ‘yes’ to accept): 请确定并输入 yes 。成功后的结果如下:
2.6.测试集群命令
-
启动客户端:redis-cli –c –h 127.0.0.1 –p 6379 , 可以跟任何节点的端口
-
查看整个集群:cluster info
-
查看当前Redis:info replication
-
查看槽位:cluster nodes
3.Java链接Redis集群
3.1.使用jedis链接集群 用到了JedisCluster这个类
@Test
public void testCluster() throws IOException, InterruptedException {
Set<HostAndPort nodes = new HashSet<();
nodes.add(new HostAndPort("127.0.0.1", 6379));
nodes.add(new HostAndPort("127.0.0.1", 6380));
nodes.add(new HostAndPort("127.0.0.1", 6381));
nodes.add(new HostAndPort("127.0.0.1", 6382));
nodes.add(new HostAndPort("127.0.0.1", 6383));
nodes.add(new HostAndPort("127.0.0.1", 6384));
JedisCluster cluster = new JedisCluster(nodes);
try {
String res = cluster.get("name");
System.out.println(res);
//cluster.quit();
} catch (Exception e) {
e.printStackTrace();
//cluster.quit();
}
}
3.2.Spring-boot-data-redis操作Redis
1.导入依赖
<!--整合Redis , 底层可以用jedis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2.redis配置
spring:
redis:
password: 123456
jedis:
pool:
max-wait: 2000ms
min-idle: 2
max-idle: 8
cluster:
nodes:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381
- 127.0.0.1:6382
- 127.0.0.1:6383
- 127.0.0.1:6384
3.测试
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
3.3.Redission连接Redis集群
1.配置Reidsson
@Configuration
public class RedissonConfig {
//创建客户端
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
//config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456");
config.useClusterServers()
.addNodeAddress("redis://127.0.0.1:6379","redis://127.0.0.1:6380","redis://127.0.0.1:6381","redis://127.0.0.1:6382","redis://127.0.0.1:6383","redis://127.0.0.1:6384")
.setPassword("123456");
return Redisson.create(config);
}
}
@Autowired
private RedissonClient redissonClient ;
四.总结
1.重点
- Redis三种集群,及优缺点
1.5.集群和分布式相关概念 - 5☆
- Redis集群搭建
- Redis集群链接
2.面试必备
-
项目中那些地方用到Redis,怎么用的?
-
Redis有哪些存储结构?每种结构说4个命令
-
Redis怎么实现栈和队列? list
-
说一下Redis-cluster集群是怎么存储数据的?
-
Redis内存不够了怎么办? 淘汰策略,集群
-
Redis集群方式有哪些?
-
Redis主从是如何同步数据的(主从原理) 全量铜鼓和增量通过
-
简单说一下主备切换时Redis如何选举master的?
哨兵:
redis-cluster:
redis-cluster是redis3.0实现集群方案,基于hash槽位实现,多个主节点按区间均分16384个槽位 ,并且为做数据冗余,还可以为每个主节点配置多个节点.
数据存放:
数据获取:
-
说一下Redis持久化方案?
-
说一下Redis淘汰策略?
-
Redis为什么那么快
内存 单线程 epool(相当叼)
-
Redis的事务和Mysql事务有什么区别
-
Redis主从有什么优缺点,哨兵有什么优缺点,cluster集群有什么优缺点?
-
reids存储数据,存储对象你一般用什么存储 string:json字符串
-
排行榜用什么来做 zset