缓存穿透是指查询一个数据库一定不存在的数据。
我们以前正常的使用Redis缓存的流程大致是:
1、数据查询首先进行缓存查询
2、如果数据存在则直接返回缓存数据
3、如果数据不存在,就对数据库进行查询,并把查询到的数据放进缓存
4、如果数据库查询数据为空,则不放进缓存
例如我们的数据表中主键是自增产生的,所有的主键值都大于0。此时如果用户传入的参数为-1,会是
怎么样?这个-1,就是一定不存在的对象。程序就会每次都去查询数据库,而每次查询都是空,每次又
都不会进行缓存。假如有人恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮我们的数据
库。
为了防止有人利用这个漏洞恶意攻击我们的数据库,我们可以采取如下措施:
如果从数据库查询的对象为空,也放入缓存,key为用户提交过来的主键值,value为null,只是设定的
缓存过期时间较短,比如设置为60秒。这样下次用户再根据这个key查询redis缓存就可以查询到值了
(当然值为null),从而保护我们的数据库免遭攻击。
缓存雪崩,是指在某一个时间段,缓存集中过期失效。在缓存集中失效的这个时间段对数据的访问查
询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
为了避免缓存雪崩的发生,我们可以将缓存的数据设置不同的失效时间,这样就可以避免缓存数据在某
个时间段集中失效。例如对于热门的数据(访问频率高的数据)可以缓存的时间长一些,对于冷门的数
据可以缓存的时间段一些。甚至对于一些特别热门的数据可以设置永不过期
缓存击穿,是指一个key非常热点(例如双十一期间进行抢购的商品数据),在不停的扛着大并发,大
并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求到数据
库上,就像在一个屏障上凿开了一个洞。
我们同样可以将这些热点数据设置永不过期就可以解决缓存击穿的问题了。
单台Redis服务性能不足的问题。这就需要使用到Redis的集群了。Redis集群有多种方案,下面分别进
行讲解。
redis支持主从复制的模式。
在主从复制模式下Redis节点分为两种角色:主节点(也称为master)和从节点(也称为slave)。这种模式
集群是由一个主节点和多个从节点构成。
原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来
同步数据。
这是一个典型的分布式读写分离模型。我们可以利用master来处理写操作,slave提供读操作。这样可
以有效减少单个机器的并发访问数量。
要实现主从复制这种模式非常简单,主节点不用做任何修改,直接启动服务即可。从节点需要修改
redis.conf配置文件,加入配置:slaveof <主节点ip地址> <主节点端口号>,例如master的ip地址为
192.168.200.129,端口号为6379,那么slave只需要在redis.conf文件中配置slaveof 192.168.200.129
6379即可。
分别连接主节点和从节点,测试发现主节点的写操作,从节点立刻就能看到相同的数据。但是在从节点
进行写操作,提示 READONLY You can’t write against a read only slave 不能写数据到从节
点。
现在我们就可以通过这种方式配置多个从节点进行读操作,主节点进行写操作,实现读写分离
下面以6380为主配置,6379和6381位从
6380.conf
daemonize yes
port 6380
dir "/usr/local/redis/data"
logfile "6380.log"
6379
# 配置redis后台进程启动
daemonize yes
# 配置redis服务器端口
port 6379
# 配置redis服务器文件保存路径(rdb aop log)
dir "/usr/local/redis/data"
# 配置redis生成的日志文件名称
logfile "6379.log"
# Generated by CONFIG REWRITE
replicaof 127.0.0.1 6380
6381
daemonize yes
port 6381
dir "/usr/local/redis/data"
logfile "6381.log"
# Generated by CONFIG REWRITE
replicaof 127.0.0.1 6380
启动命令
redis-server …/conf/redis-6379.conf
我们现在已经给Redis实现了主从复制,可将主节点数据同步给从节点,实现了读写分离,提高Redis的
性能。但是现在还存在一个问题,就是在主从复制这种模式下只有一个主节点,一旦主节点宕机,就无
法再进行写操作了。也就是说主从复制这种模式没有实现高可用。那么什么是高可用呢?如何实现高可
用呢?
高可用(HA)是分布式系统架构设计中必须考虑的因素之一,它是通过架构设计减少系统不能提供服务的
时间。保证高可用通常遵循下面几点:
sentinel(哨兵)是用于监控redis集群中Master状态的工具,其本身也是一个独立运行的进程,是Redis
的高可用解决方案,sentinel哨兵模式已经被集成在redis2.4之后的版本中。
sentinel可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master
服务下线时,自动将该master下的某个从服务升级为master服务替代已下线的master服务继续处理请
求,并且其余从节点开始从新的主节点复制数据。
在redis安装完成后,会有一个redis-sentinel的文件,这就是启动sentinel的脚本文件,同时还有一个
sentinel.conf文件,这个是sentinel的配置文件。
sentinel工作模式:
注意:可能有些同学会有疑问,现在我们已经基于sentinel实现了高可用,但是如果sentinel挂了怎么
办呢?其实sentinel本身也可以实现集群,也就是说sentinel也是高可用的。
配置三个redis sentinel
26379
# 哨兵端口
port 26379
# 后台启动
daemonize yes
# 数据目录
dir "/usr/local/redis/data"
# 日志名称
logfile "26379.log"
# 哨兵配置 哨兵一般是奇数个 数量一般设置成一半+1
sentinel myid 08793350dc3c28bfe8cd1fb4d33f2150c8ae03cc
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
protected-mode no
sentinel monitor mymaster 127.0.0.1 6381 2
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-replica mymaster 127.0.0.1 6380
sentinel known-replica mymaster 127.0.0.1 6379
sentinel known-sentinel mymaster 127.0.0.1 26381 00ca2a7afad0fba94f03685ba80d3665469c41b0
sentinel known-sentinel mymaster 127.0.0.1 26380 3324d88d9af7ba49ab9b0c845e0fa2c19f36fdb2
sentinel current-epoch 1
26380
port 26380
daemonize yes
dir "/usr/local/redis/data"
logfile "26380.log"
sentinel myid 3324d88d9af7ba49ab9b0c845e0fa2c19f36fdb2
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
protected-mode no
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 2
sentinel leader-epoch mymaster 2
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-replica mymaster 127.0.0.1 6379
sentinel known-sentinel mymaster 127.0.0.1 26379 08793350dc3c28bfe8cd1fb4d33f2150c8ae03cc
sentinel known-sentinel mymaster 127.0.0.1 26381 00ca2a7afad0fba94f03685ba80d3665469c41b0
sentinel current-epoch 2
26381
port 26381
daemonize yes
dir "/usr/local/redis/data"
logfile "26381.log"
sentinel myid 00ca2a7afad0fba94f03685ba80d3665469c41b0
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
protected-mode no
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 2
sentinel leader-epoch mymaster 2
sentinel known-replica mymaster 127.0.0.1 6379
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26379 08793350dc3c28bfe8cd1fb4d33f2150c8ae03cc
sentinel known-sentinel mymaster 127.0.0.1 26380 3324d88d9af7ba49ab9b0c845e0fa2c19f36fdb2
sentinel current-epoch 2
参数说明:
sentinel monitor mymaster 192.168.200.129 6379 1
mymaster 主节点名,可以任意起名,但必须和后面的配置保持一致。
192.168.200.128 6379 主节点连接地址。
1 将主服务器判断为失效需要投票,这里设置至少需要 1个 Sentinel 同意。
sentinel down-after-milliseconds mymaster 10000
设置Sentinel认为服务器已经断线所需的毫秒数。
sentinel failover-timeout mymaster 60000
设置failover(故障转移)的过期时间。当failover开始后,在此时间内仍然没有触发任何failover
操作,当前 sentinel 会认为此次failover失败。
sentinel parallel-syncs mymaster 1
设置在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越
小,表示同时进行同步的从服务器越少,那么完成故障转移所需的时间就越长。
启动命令
redis-sentinel …/conf/sentinel-26379.conf
info可查看配置
主
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
从
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,
port=6381,state=online,offset=80531,lag=1
选举方案
Redis Cluster是Redis的内置集群,在Redis3.0推出的实现方案。在Redis3.0之前是没有这个内置集群
的。Redis Cluster是无中心节点的集群架构,依靠Gossip协议协同自动化修复集群的状态。
Redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等
的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连
接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他
节点的数据。
Redis cluster集群架构图如下
需要注意的是,这种集群模式下集群中每个节点保存的数据并不是所有的数据,而只是一部分数据。那
么数据是如何合理的分配到不同的节点上的呢?
Redis 集群是采用一种叫做 哈希槽 (hash slot) 的方式来分配数据的。redis cluster 默认分配了
16384 个slot,当我们set一个key 时,会用 CRC16 算法来取模得到所属的 slot ,然后将这个key 分到
哈希槽区间的节点上,具体算法就是: CRC16(key) % 16384 。
三个节点分别承担的slot 区间是:
节点A覆盖0-5460
节点B覆盖5461-10922
节点C覆盖10923-16383
那么,现在要设置一个key ,比如叫 my_name :
按照redis cluster的哈希槽算法: CRC16(‘my_name’)%16384 = 2412 。 那么就会把这个key 的存储分
配到 节点A 上了。
redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点
提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会在这些从节点中选取一
个来充当主节点,从而保证集群不会挂掉。
redis cluster加入了主从模式后的效果如下:
这里准备了6台redis的配置文件,只需要配置文件启动即可,而不需要放好多个redis
6379
daemonize yes
port 6379
dir /usr/local/redis/data
logfile "6379.log"
cluster-enabled yes
cluster-config-file "nodes-6379.conf"
cluster-node-timeout 10000
6380
daemonize yes
port 6380
dir "/usr/local/redis/data"
logfile "6380.log"
cluster-enabled yes
cluster-config-file "nodes-6380.conf"
cluster-node-timeout 10000
后面都一样了,主要是端口和配置文件的节点。然后是cluster-enabled yes必须配置
觉得启动麻烦可以写个shell脚本
vi start-all.sh
cd node1 ./redis-server redis.conf
cd .. cd node2 ./redis-server redis.conf
cd .. cd node3 ./redis-server redis.conf
cd .. cd node4 ./redis-server redis.conf
cd .. cd node5 ./redis-server redis.conf
cd ..后面一样
设置脚本的权限,并启动:
chmod 744 start-all.sh ./start-all.sh
./redis-cli --cluster create 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 --cluster-replicas 1
可能会出现节点有参数的情况,链接redis后
flushall清空
key * 查看所有
如果群启动失败,记得先把所有的redis关了,然后把log日志全部情况再尝试