Redis高级

一、Redis主从复制

概述

1、redis的复制功能是支持多个数据库之间的数据同步。一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。

2、通过redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力。主数据库主要进行写操作,而从数据库负责读操作。

 

主从复制过程:见下图

 

 

 

过程:

1:当一个从数据库启动时,会向主数据库发送sync命令,

2:主数据库接收到sync命令后会开始在后台保存快照(执行rdb操作),并将保存期间接收到的命令缓存起来

3:当快照完成后,redis会将快照文件和所有缓存的命令发送给从数据库。

4:从数据库收到后,会载入快照文件并执行收到的缓存的命令。

 

进行配置过程

  一主多从实现

  介绍:  主服务器可以读写,但是从服务器只允许读。

  场景:

  •  读写分离(读、写分别不同的库,增加整体的吞吐量)、
  • 日志备份、高可用读写分离问题:
  • 同步(redis自带解决方案)

 

Redis只能一个主,多个从:

 

 

过程(使用内网实现的通讯):

1、 从服务器启动时候,会向Master发送sync命令.从服务器是指向主服务器的IP和端口号。

2、当Master接收到sync命令后,会开始在后台保存快照(执行rdb操作),并将保存期间接收到的命令缓存起来。(一旦在主服务器有任何写的操作,都会有快照文件记录)

3、当快照完成后,redis会将快照文件和所有缓存的命令发送给Slave。

 

修改slave从redis中的 redis.conf文件

slaveof  ip + 端口 
masterauth 123456--- 主redis服务器配置了密码,则需要配置

 

直接服务器配置

 

 

  配置好了,启动主,再启动从。

 

结果验证:

 主服务器写入:

 

 

 从服务器可以读

 

 从服务器不可以写!

 

 

 

可以通过 info 查看标志:

信息一目了然

 

一个主 多个从的话 那就每个从都设置下 , 只能有一个主!!

 

二、Redis持久化

 什么是Redis持久化?

  •  就是将内存数据保存到硬盘。

Redis 持久化存储方式:

  •  AOF
  •  RDB

 

 解释:

1. RDB 是以二进制文件,是在某个时间 点将数据写入一个临时文件(60s set 10个key),持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能。开启单独的进程去做写的io操作和当前redis主进程没有任何关联。 
缺点:RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候,这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置redis 在 n 秒内如果超过 m 个 key 被修改这执行一次 RDB 操作。这个操作就类似于在这个时间点来保存一次 Redis 的所有数据,一次快照数据。所有这个持久化方法也通常叫做 snapshots。Redis的值存放在内存中,防止突然断电。对数据进行持久化的备份。非实时,突然断电,可能有一部分数据丢失

         

 验证RDB

 1.写入值 then 宕机

2.启动,读取值

3.默认开启了 rdb持久化

 

结论:

删除掉,在开启就查不到了哦。当服务器宕机后,以RDB进行持久化

配置文件就可以找到这个默认的配置:

 

在slave中:

 

 

300s 内做了 10次文件的保存 会生产rdb文件记录.

 

解释备注:

#dbfilename:持久化数据存储在本地的文件

dbfilename dump.rdb

#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下启动的redis-cli,则数据会存储在当前src目录下

dir ./

##snapshot触发的时机,save   

##如下为900秒后,至少有一个变更操作,才会snapshot 

##对于此值的设置,需要谨慎,评估系统的变更操作密集程度 

##可以通过“save “””来关闭snapshot功能 

#save时间,以下分别表示更改了1个key时间隔900s进行持久化存储;更改了10个key300s进行存储;更改10000个key60s进行存储。

save 900 1

save 300 10

save 60 10000

##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等 

stop-writes-on-bgsave-error yes 

##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间 

rdbcompression yes 

 

2.AOF,Append-only file,将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在 append 操作返回后(已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当 server 需要数据恢复时,可以直接 replay 此日志文件,即可还原所有的操作过程。AOF 相对可靠,它和 mysql 中 bin.log、apache.log、zookeeper 中 txn-log 简直异曲同工。AOF 文件内容是字符串,非常容易阅读和解析。我们可以简单的认为 AOF 就是日志文件,此文件只会记录“变更操作”(例如:set/del 等),如果 server 中持续的大量变更操作,将会导致 AOF 文件非常的庞大,意味着 server 失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条 AOF 记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为 AOF 持久化模式还伴生了“AOF rewrite”。
AOF 的特性决定了它相对比较安全,如果你期望数据更少的丢失,那么可以采用 AOF 模式。如果 AOF 文件正在被写入时突然 server 失效,有可能导致文件的最后一次记录是不完整,你可以通过手工或者程序的方式去检测并修正不完整的记录,以便通过AOF 文件恢复能够正常;同时需要提醒,如果你的 redis 持久化手段中有 AOF ,那么在 server 故障失效后再次启动前,需要检测AOF 文件的完整性。

优点:可以保持更高的数据完整性,如果设置追加 file 的时间是 1s,如果 redis 发生故障,最多会丢失 1s 的数据;且如果日志写入不完整支持 redis-check-aof 来进行日志修复;AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)。

缺点:AOF 文件比 RDB 文件大,且恢复速度慢。

 

验证AOF

AOF 实时日志记录形式 只会记录set之类的 写的操作  

1.配置时候 appendonly yes  就OK了

2.然后进行写入值:

3.最后看到这个文件:

这个日志文件 只会存放写的日志文件

get之类的肯定不会记录的哦 只会记录增 、删、 改的操作.由于是实时的 效率低 影响整体性能  AOF庞大的话 就很影响整体性能了。如果突然断电这样的情况 肯定AOF好!

 

总结:

AOF 是文件操作,对于变更操作比较密集的 server,那么必将造成磁盘 IO 的负荷加重;此外 linux 对文件操作采取了“延迟写入”手段,即并非每次 write 操作都会触发实际磁盘操作,而是进入了 buffer 中,当 buffer 数据达到阀值时触发实际写入(也有其他时机),这是 linux 对文件系统的优化,但是这却有可能带来隐患,如果 buffer 没有刷新到磁盘,此时物理机器失效(比如断电),那么有可能导致最后一条或者多条 AOF记录的丢失。通过上述配置文件,可以得知 redis 提供了 3 中 AOF记录同步选项:

1.always:每一条AOF 记录都立即同步到文件,这是最安全的方式,也以为更多的磁盘操作和阻塞延迟,是 IO 开支较大。

2.everysec:每秒同步一次,性能和安全都比较中庸的方式,也是 redis 推荐的方式。如果遇到物理服务器故障,有可能导致最近一秒内 AOF 记录丢失(可能为部分丢失)。

3.no:redis 并不直接调用文件同步,而是交给操作系统来处理,操作系统可以根据 buffer 填充情况 / 通道空闲时间等择机触发同步;这是一种普通的文件操作方式。性能较好,在物理服务器故障时,数据丢失量会因 OS 配置有关。

其实,我们可以选择的太少,everysec 是最佳的选择。如果你非常在意每个数据都极其可靠,建议你选择一款“关系性数据库”吧。
AOF 文件会不断增大,它的大小直接影响“故障恢复”的时间, 而且 AOF 文件中历史操作是可以丢弃的。AOF rewrite 操作就是“压缩”AOF 文件的过程,当然 redis 并没有采用“基于原 aof 文件”来重写的方式,而是采取了类似 snapshot 的方式:基于 copy-on-write,全量遍历内存中数据,然后逐个序列到 aof 文件中。因此 AOF rewrite 能够正确反应当前内存数据的状态,这正是我们所需要的;*rewrite 过程中,对于新的变更操作将仍然被写入到原 AOF 文件中,同时这些新的变更操作也会被 redis 收集起来(buffer,copy-on-write 方式下,最极端的可能是所有的 key 都在此期间被修改,将会耗费 2 倍内存),当内存数据被全部写入到新的 aof 文件之后,收集的新的变更操作也将会一并追加到新的 aof 文件中,此后将会重命名新的 AOF文件为 appendonly.aof, 此后所有的操作都将被写入新的 aof 文件。如果在 rewrite 过程中,出现故障,将不会影响原 AOF 文件的正常工作,只有当 rewrite 完成之后才会切换文件,因为 rewrite 过程是比较可靠的。*

触发 rewrite 的时机可以通过配置文件来声明,同时 redis 中可以通过 bgrewriteaof 指令人工干预。

redis-cli -h ip -p port bgrewriteaof

因为 rewrite 操作 /aof 记录同步 /snapshot 都消耗磁盘 IO,redis 采取了“schedule”策略:无论是“人工干预”还是系统触发,snapshot 和 rewrite 需要逐个被执行。

AOF rewrite 过程并不阻塞客户端请求。系统会开启一个子进程来完成。

 

备注:

##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能  ##只有在“yes”下,aof重写/文件同步等特性才会生效 

appendonly yes 

##指定aof文件名称 

appendfilename appendonly.aof 

##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec 

appendfsync everysec 

##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no” 

no-appendfsync-on-rewrite no 

 

##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb” 

auto-aof-rewrite-min-size 64mb 

 
##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。 

##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后 

##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。  

 auto-aof-rewrite-percentage 100  

 

 

Redis哨兵机制

什么是哨兵机制

哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master.

每个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机” Subjective Down,简称sdown).

若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡"(即:客观上的真正down机,Objective Down,简称odown),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置.

虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵(sentinel).

哨兵(sentinel) 的一些设计思路和zookeeper非常类似

单个哨兵(sentinel)

Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:

  • 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
  • 提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。

 

哨兵单独的一个程序 监听集群服务器

  做心跳检测时候(发命令包),检测到Master宕机了,就从其余的Slave中,通过投票重新选举Master角色。 这是原Master复活后,成为了Slave(不用人为改写配置文件)

 

 1. Redis哨兵机制(配置简单)心跳检测、故障转移(选举策略)、监控

 2.在Redis中只允许有一个主服务器,可以允许多个从服务器

 

    

 

 哨兵机制配置:

哨兵模式修改配置

实现步骤:

1.拷贝到etc目录

cp sentinel.conf  /usr/local/redis/etc

2.修改sentinel.conf配置文件

sentinel monitor mymast  192.168.110.133 6379 1  #主节点 名称 IP 端口号 选举次数

sentinel auth-pass mymaster 123456 

3. 修改心跳检测 30毫秒

sentinel down-after-milliseconds mymaster 30

4.sentinel parallel-syncs mymaster 2 --- 做多多少合格节点

5. 启动哨兵模式

./redis-server /usr/local/redis/etc/sentinel.conf --sentinel &

6. 停止哨兵模式

 

准备三台虚拟机,开始玩儿~

三台虚拟机互相pin通

然后开始修改 conf 文件, slaveof   masterauth 分别指向主服务器

先启动主 然后从  

通过info看到:

集群成功!

在主写入值 其他都收到

 

 哨兵的安装:

 哨兵是独立的应用的程序  在某一台服务器上

首先进入到 redis 源码目录中

cd /home/redis/redis-3.2.9

然后:

然后修改这个配置文件:

vi /usr/local/redis/etc/sentinel.conf

2.修改sentinel.conf配置文件

sentinel monitor mymast  192.168.91.1 6379 1  #主节点 名称 IP 端口号 选举次数

sentinel auth-pass mymaster 123

3. 修改心跳检测 30毫秒

sentinel down-after-milliseconds mymaster 30

4.sentinel parallel-syncs mymaster 2 --- 做多多少合格节点

 修改:

修改为:

改成实时的

 

 停止redis集群 重新启动

 

 然后重新开始,先启动哨兵 然后启动redis  

 分别启动后

然后启动哨兵程序: 

./redis-server /usr/local/redis/etc/sentinel.conf --sentinel &

启动会打印日志信息:

 

此时哨兵自己读取出来了 slave 和 master信息

这时候哨兵开始工作了

一旦主节点挂断了 他会进行重新的选举

 

 

Redis事物

redis集群对象JedisCluster不支持事务,但是,集群里面的每个节点支持事务,但是可以用第三方呀!

首先启动下,然后看看事务问题:

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9001/redis/etc/redis.conf

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9002/redis/etc/redis.conf

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9003/redis/etc/redis.conf

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9004/redis/etc/redis.conf

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9005/redis/etc/redis.conf

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9006/redis/etc/redis.conf

启动集群:

/usr/local/redis-cluster/bin/redis-trib.rb create --replicas 1 192.168.91.5:9001 192.168.91.5:9002 192.168.91.5:9003 192.168.91.5:9004 192.168.91.5:9005 192.168.91.5:9006

 

连接一个节点:9001

可以看到 已经转到9002这个节点了

然后 在9001上面 开启事务 然后 写入值 自动转到了 9002上面 在没有提价事务的时候 竟然可以查到!

 

如果再同一个节点:

竟然查不到!

提交后就可以了!

 结论:

redis集群不可以支持事务!!  但是单个节点支持!!Redis+Lua语言可以实现  通过开发第三方插件

 总结;

对于redis来说,只满足其中的:一致性和隔离性两个特性,其他特性是不支持的。

关于redis对ACID四个特性暂时先说这么多,在本文后面会详细说明。在详述之前,我们先来了解redis事务具体的使用和实现,这样我们接下来讨论ACID时才能更好的理解。

 

关于Redis事务的使用

Redis事务主要命令包括

  • MULTI
  • EXEC
  • DISCARD
  • WATCH

下面进行一一介绍:

1. MULTI命令

MULTI命令用来开启一个事务,当MULTI执行之后,客户端可以继续向服务器发送多条命令,这些命令会缓存在队列里面,只有当执行EXEC命令时,这些命令才会执行。

而DISCARD命令可以清空事务队列,放弃执行事务。

一个使用MULTI和EXEC执行事务的例子:

一个事务从开始到执行会经历以下三个阶段:

  1. 开始事务。
  2. 命令入队。
  3. 执行事务。

2. EXEC命令

 使用redis事务可能会产生错误,主要分为两大类:

  • 事务在执行EXEC之前,入队的命令可能出错。
  • 命令可能在 EXEC 调用之后失败

Redis在2.6.5之后,如果发现事务在执行EXEC之前出现错误,那么会放弃这个事务。在EXEC命令之后产生的错误,会被忽略,其他正确的命令会被继续执行。

 

3 .DISCARD

 

4. WATCH

WATCH命令可以添加监控的键,如果这些监控的键没有被其他客户端修改,那么事务可以顺利执行,如果被修改了,那么事务就不能执行。

 

 

Redis事务不支持回滚

以下是这种做法的优点:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。 有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。 举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

鉴于没有任何机制能避免程序员自己造成的错误, 并且这类错误通常不会在生产环境中出现, 所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。 

 

Redis事务的ACID性质讨论

 1.原子性

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的

如果一个事务队列中的所有命令都被成功地执行,那么称这个事务执行成功

另一方面,如果 Redis 服务器进程在执行事务的过程中被停止 —— 比如接到 KILL 信号、宿主机器停机,等等,那么事务执行失败

事务失败时,Redis 也不会进行任何的重试或者回滚动作,不满足要么全部全部执行,要么都不执行的条件

2.一致性

一致性分下面几种情况来讨论:

首先,如果一个事务的指令全部被执行,那么数据库的状态是满足数据库完整性约束的

其次,如果一个事务中有的指令有错误,那么数据库的状态是满足数据完整性约束的

最后,如果事务运行到某条指令时,进程被kill掉了,那么要分下面几种情况讨论:

  • 如果当前redis采用的是内存模式,那么重启之后redis数据库是空的,那么满足一致性条件
  • 如果当前采用RDB模式存储的,在执行事务时,Redis 不会中断事务去执行保存 RDB 的工作,只有在事务执行之后,保存 RDB 的工作才有可能开始。所以当 RDB 模式下的 Redis 服务器进程在事 务中途被杀死时,事务内执行的命令,不管成功了多少,都不会被保存到 RDB 文件里。 恢复数据库需要使用现有的 RDB 文件,而这个 RDB 文件的数据保存的是最近一次的数 据库快照(snapshot),所以它的数据可能不是最新的,但只要 RDB 文件本身没有因为 其他问题而出错,那么还原后的数据库就是一致的

  • 如果当前采用的是AOF存储的,那么可能事务的内容还未写入到AOF文件,那么此时肯定是满足一致性的,如果事务的内容有部分写入到AOF文件中,那么需要用工具把AOF中事务执行部分成功的指令移除,这时,移除之后的AOF文件也是满足一致性的

所以,redis事务满足一致性约束

2.隔离性

Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

4.持久性

因为事务不过是用队列包裹起了一组 Redis 命令,并没有提供任何额外的持久性功能,所以事务的持久性由 Redis 所使用的持久化模式决定

  • 在单纯的内存模式下,事务肯定是不持久的
  • 在 RDB 模式下,服务器可能在事务执行之后、RDB 文件更新之前的这段时间失败,所以 RDB 模式下的 Redis 事务也是不持久的
  • 在 AOF 的“总是 SYNC ”模式下,事务的每条命令在执行成功之后,都会立即调用 fsync 或 fdatasync 将事务数据写入到 AOF 文件。但是,这种保存是由后台线程进行的,主线程不会阻塞直到保存成功,所以从命令执行成功到数据保存到硬盘之间,还是有一段非常小的间隔,所以这种模式下的事务也是不持久的。
  • 其他 AOF 模式也和“总是 SYNC ”模式类似,所以它们都是不持久的。

Spring Boot2.0之 整合Redis事务

 

 Redis实现中间件

什么是消息中间件

  • 发布订阅
  • 点对点 
  • 消息中间件本身是异步的通讯

 

Redis发布订阅原理:

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis 客户端可以订阅任意数量的频道。

 

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

 

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

 

client2 去发布主题 channel1主题  client5和client1订阅主题

client2发布一个主题  其他的去订阅 消费掉

 

Redis实现步骤:

两个redis客户端去连接,

首先创建频道:

另外开启一个客户端,往这个频道发送值

可以观察第一个客户端:

结论:发布一个 订阅 一个,生产者 消费者。

  

Redis雪崩效应以及解决方案

缓存雪崩产生的原因

缓存雪崩通俗简单的理解就是:由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从Redis中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机,造成系统的崩溃。

 

缓存失效的时候如下图:

 

缓存失效时的雪崩效应对底层系统的冲击非常可怕!那有什么办法来解决这个问题呢?基本解决思路如下:

  第一,大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,避免缓存失效时对数据库造成太大的压力,虽然能够在一定的程度上缓解了数据库的压力但是与  此同时又降低了系统的吞吐量。

 第二,分析用户的行为,尽量让缓存失效的时间均匀分布。

 第三,如果是因为某台缓存服务器宕机,可以考虑做主备,比如:redis主备,但是双缓存涉及到更新事务的问题,update可能读到脏数据,需要好好解决。

 

解决方案

1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

     注意: 加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的 方法。

2:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

3:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期(此点为补充)

 

架构如下所示时候:

 

 

如何攻击Redis?

如果再redis中有1000个key,如果同一时间失效?   直接查数据库了 不再走redis了 ! 大连查询请求过来,,,,产生了雪崩效应~

这时候使用 限流 服务降级、熔断 的方案  这三个方案是针对redis的上一层的

 

Redis雪崩效应的解决方案

1、可以使用分布式锁   单机版的话本地锁

2、消息中间件方式

3、一级和二级缓存 Redis+Ehchache

4、均摊分配Redis的key的失效时间

 

解释:

 1、  当突然有大量请求到数据库服务器时候,进行请求限制。使用所的机制,保证只有一个线程(请求)操作。否则进行排队等待(集群分布式锁,单机本地锁)。减少服务器吞吐量,效率低。

 加入锁!

 

保证只能有一个线程进入  实际上只能有一个请求在执行查询操作

也可以在此处进行使用限流的策略~

 

2、使用消息中间件解决

  这种方案是最靠谱的方案!

   消息中间件 可以解决高并发!!!

  如果大量的请求进行访问时候,Redis没有值的情况,会将查询的结果存放在消息中间件中(利用了MQ异步步特性

   查不到时候 走MQ  

 

 

如果redis查询不到结果的情况,这个时候直将该消息放到中间件,

消费者最多能够承受50个消息

如果生产者发送100个消息,有90个请求等待ing.....

3、一级二级缓存参考: https://www.cnblogs.com/toov5/p/9892910.html

4、均摊分配redis key的失效时间 

     不让在同一时间失效,不同key失效时间不同 哈哈

 

 

缓存穿透

   Redis穿透问题解决方案

posted @ 2019-03-01 02:15  toov5  阅读(196)  评论(0编辑  收藏  举报