文章目录
一.集群概念
1.为什么要集群
- 解决单点故障
- 实现高可用
2.什么是集群
集群就是多个服务器做相同的事情,每个服务器都是完整的一个应用,多个服务器是复制的概念(做的业务,包含的模块都是一样的)
3.集群应该具有如下特性:
- 可扩展性
- 高可用性
4.集群能力
集群应该具备如下能力:
-
负载均衡
把请求根据某种算法相对平衡的路由到集群的应用
-
错误恢复
集群下的某个应用挂了需要找到能用的服务继续处理请求
-
主备切换
对于应用的集群,某个应用挂掉了,集群中需要有其他的应用顶上以处理请求。
二.分布式概念
2.什么是分布式
分布式就是多个服务器做不同的事情,每个服务器只是负责整个项目的一部分功能,所有服务器合起来才是一个完成的应用
三.Redis集群模式
Redis为什么做集群
- 防止单点故障
- 处理高并发
- 处理大量数据
Redis的三种集群模式
1.主从复制(读写分离)
就一个主Redis,多个从Redis, 从Redis的数据是主Redis复制过来的 , 写操作(保存,删除,修改,查询)请求主Redis
而从Redis只能读
好处:分担读的压力
缺点:不分担些的压力 ,不解决数据量大的问题 ,主挂了,没办法自动的提升从为主
主从复制的作用
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时可以由从节点提供服务实现快速的故障恢复;实际上是一种服务的冗余
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量。
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
主从的缺点
不具备自动容错和恢复功能
:主从宕机会影响前端的部分请求失败,需要重启机器或者手动切换前端IP才能恢复
主机宕机数据丢失
:宕机前部分有部分数据未同步到从机,切换IP后会引入数据不一致降低系统可用性
数据大的问题
:数据量特别大一个主是存储不了
2.Redis哨兵
在主从的基础上增加了哨兵,监控主的健康状态,自动的进行从到主的提升
主观下线:哨兵监控到ping不到主,主观认为主挂掉了
客观下线:超过一半哨兵监控到ping不到主,客观认为主挂掉了
故障转移:将从转为主
3.Redis-cluster集群
什么是集群
多主多从,多主实现了分布式数据存储,多主之间相互关联
数据存储方案
分布式数据存储 , 槽位运算 ,算法CRC16(key) % 16384
四.搭建Redis-cluster集群
1.环境准备
1.1.Redis 3.2
需要 6 台 redis 服务器。搭建伪集群。
需要 6 个 redis 实例。
需要运行在不同的端口 6379-6384
1.2.Ruby语言运行环境
我们需要使用ruby脚本来实现集群搭建
-
Ruby 打包系统RubyGems
RubyGems简称gems,是一个用于对 Ruby组件进行打包的 Ruby 打包系统
-
Redis的Ruby驱动redis-xxxx.gem
-
创建Redis集群的工具redis-trib.rb
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驱动
1.解压Ruby驱动(rubygems-2.7.7) , 进入根目录,执行
ruby setup.rb
2.切入到Redis目录执行(6379的Redis目录) gem install redis
2.5.执行集群构建脚本
1.启动6个Redis
2.拷贝redis-trib.rb到Redis目录(6379的Redis目录)
3.在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
4.在出现 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
五.Java链接测试Redis-cluster集群
创建一个maven普通项目,手动导入jar包
集群代码测试
@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 {
cluster.set("name","古大哥");
String res = cluster.get("name");
System.out.println(res);
//cluster.quit();
} catch (Exception e) {
e.printStackTrace();
//cluster.quit();
}
}
六、缓存穿透/缓存击穿/缓存雪崩
缓存穿透
描述:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
-
设置热点数据永远不过期。
-
加互斥锁,互斥锁参考代码如下:
说明:1)缓存中有数据,直接走上述代码13行后就返回结果了 2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。 3)当然这是简化处理,理论上如果能根据key值加锁就更好了,就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据,上面代码明显做不到这点。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
- 设置热点数据永远不过期。