一、Redis事务
(一)Redis的事务就是一组命令的集合,事务中的命令都会被序列化。并且具有三个特性:一次性,顺序性,排他性。单条命令保证原子性,但事务不保证原子性,且没有回滚,也就是说事务中有一条命令执行失败后,其余命令会按照顺序继续执行。
(二)Redis事务的三个阶段
1、开始事务
2、命令入队
3、执行事务
(三)Redis事务的相关命令
1、watch key1 key2(监视多个key,如果在事务执行之前,被监视的key被其他命令改动,事务会被打断)
2、multi(表示事务的开始)
3、exec(执行事务内的命令)
4、discard(取消事务)
5、unwatch(取消watch对所有key的监控)
二、watch监控
(一)悲观锁:每次操作数据的时候都会加锁,这样别人想拿到这个数据就会block直到拿到锁,传统的关系型数据库就用到了很多这种锁机制,比如行锁,表锁,读锁,写锁等,都是在操作之前先上锁。
(二)乐观锁:每次操作数据库的动作都不会加锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制,乐观锁适用于多读的应用类型,这样可以提高吞吐量。乐观锁策略:提交的版本必须大于当前记录的版本。
三、Redis发布订阅
(一)是什么:Redis发布订阅(pub/sub)是一种消息通信模式,发送者在向消息队列发送消息后,订阅者可以从队列中拿到消息。Redis客户端可以订阅任意数量的频道。
(二)基本步骤:发布者创建一个频道,订阅者订阅这个频道后,当发布者在用publish命令向频道中发布消息的时候,订阅者的控制台就会输出相关的消息。
原理:Redis是使用C实现的,分析源码里的pubsub.c可以加深对Redis的理解。
通过subscribe命令订阅某频道后,redis-server里维护了一个字典,字典的键就是一个个的频道channel,字典的值则是一个链表,存储着所有订阅这个channel的客户端,subscribe命令的关键就是将客户端添加到对应的channel链表中。
通过publish命令向订阅者发送消息,redis-server会使用给定的频道作为键,在它所对应的链表中遍历找出所有的订阅者,将消息发送给他们。
四、Redis主从复制
(一)概念:主从复制是指将一台redis服务器的数据复制到其他的redis服务器,前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能从主节点复制到从节点,master以写为主,slave以读为主。默认情况下,每台redis服务器都是主节点,且一个主节点可以有多个从节点,但是一个从节点只能有一个主节点。
(二)主从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
2、故障恢复:当主节点出现问题,可以由从节点继续提供服务,实现快速的故障恢复;实际上是一种服务的冗余
3、负载均衡:在主从复制的基础上,可以配合读写分离,主节点提供写服务,从节点提供读服务,分担服务器负载
4、高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是redis高可用的基础
(三)复制的原理:slave启动成功连接到master后,会发送一个sync命令。master接到命令会启动后台的存盘进程,同时收集所有接收到的用于修改数据的命令,后台进程执行完毕后,master将传送整个数据文件到slave,并完成一次完全同步
全量复制:slave在接收到数据文件之后,将其存盘并加载到内存中
增量复制:master继续将所有收集到的修改命令依次传给slave,完成同步
只要重新连接master,一次完全同步就会自动执行
五、哨兵模式
(一)主从切换技术的方法是:当主服务器宕机以后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费时费力,还会造成一段时间内的服务不可用。这不是一种推荐的方式,所以我们应该优先考虑哨兵模式。哨兵模式能够自动监控主机是否故障,如果故障了,根据投票数自动将从库切换为主库。
哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令。哨兵是一个独立的进程,作为进程,他会独立运行。其原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。
(二)哨兵模式还分为单哨兵模式和多哨兵模式
单哨兵:
1、通过发送指令,让redis服务器返回其运行状态,包括主服务器和从服务器
2、当哨兵检测到master宕机,会自动将slave切换为master,然后通过发布订阅模式通知其他从服务器,修改配置文件,让他们切换主机
然而一个哨兵进程对redis进行监控可能会出现问题,为此我们可以使用多个哨兵进行监控。各个哨兵之间还会监控,这样就形成了多哨兵模式:
1、假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行故障切换(failover),仅仅是哨兵1认为主服务器不可用,这个现象称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定的值,那么哨兵之间就会进行一次投票。投票结果由一个哨兵发起,进行failover操作。切换成功后,通过发布订阅模式,让各个哨兵把自己监控的主服务器切换为当前的主服务器,这个过程称为客观下线。
(三)哨兵模式的优点:
1、哨兵集群模式是基于主从复制的,主从复制的优点它都具备
2、主从可以切换,故障可以转移,系统的可用性更好
3、哨兵模式是主从复制的升级,可以让系统更健壮
缺点:
1、Redis较难支持在线扩容,在集群容量达到上限的时候在线扩容会变得很复杂
2、实现哨兵模式的配置也不简单,甚至可以说有点繁琐
六、缓存穿透和雪崩
(一)缓存穿透概念:用户想要查询一个数据,发现redis内存中没有,也就是缓存没有命中,于是转而向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层的数据库,这会给数据库造成极大的压力,这时候就出现了缓存穿透。
解决方案:1、布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
2、缓存空对象:当存储层不命中时,即使返回一个空对象也将其缓存起来,同时设置一个过期时间,之后再对这个数据进行的访问会直接从缓存中拿,保护了后端数据源。
(二)缓存击穿
概述:他和缓存穿透的区别是,指一个key非常热点,在不停的扛着大量的并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就想在屏幕上凿开了一个洞
解决方案:
1、设置热点数据永不过期
2、加互斥锁
(三)缓存雪崩
概述:是指在某一个时间段,缓存集中过期失效
解决方案:
1、redis高可用(既然redis可能挂掉,那就多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建集群)
2、限流降级(这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,比如对某个key设置只允许一个线程查询数据和写缓存,其它线程等待)
3、数据预热(在正式部署之前,先把可能的数据都预先访问一遍,在即将发生大并发之前,触发加载,缓存不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀点)