一、什么是redis
redis即远程字典服务,C语言编写、支持网络、可基于内存亦可持久化的日志型、“Key-Value”数据库,并提供多种语言的API;redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。
优点
Redis有哪些特点?
1、速度快
2、持久化
3、支持多种数据结构
4、支持多种编程语言
5、功能丰富、主从复制
6、高可用及分布式
二、数据类型
常用数据类型:String、List、set、Hash、Zset
特殊数据类型:Geospatail(地理位置详情)、Hyperloglog(技术统计)、BitMap
三、基本事务
操作步骤:1.开启事务(multi)2、命令入队 3、执行事务(exec)/取消事务(discard)
编译时异常,所有命令不会被执行 运行时异常,错误命令不会被执行
四、持久化(RDB、AOF)
过程:
(1)客户端向服务端发送写操作(数据在客户端的内存中)。
(2)数据库服务端接收到写请求的数据(数据在服务端的内存中)。
(3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
(4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
(5)磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。
RDB机制
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,默认的文件名为dump.rdb。提供了三种机制:save、bgsave、自动化。
1、save触发方式
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。
2、bgsave触发方式
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
3、自动触发
自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置:
①save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave。
②stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了
③rdbcompression ;默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。
④rdbchecksum :默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
⑤dbfilename :设置快照的文件名,默认是 dump.rdb
⑥dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。
RDB 的优势和劣势
①、优势
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
②、劣势
RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
AOF机制
全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。
AOF也有三种触发机制
1、每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
2、每秒同步everysec:异步操作,每秒记录 如果一秒内宕机,有数据丢失
3、不同no:从不同步
RDB和AOF到底该如何选择
五、redis的发布订阅
Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者,订阅者和Channel。
发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。Redis的这种发布订阅机制与基于主题的发布订阅类似,Channel相当于主题。
redis发布订阅内容
1、发送消息
Redis采用PUBLISH命令发送消息,其返回值为接收到该消息的订阅者的数量。
命令:publish 主题 内容
2、订阅某个频道
Redis采用SUBSCRIBE命令订阅某个频道,其返回值包括客户端订阅的频道,目前已订阅的频道数量,以及接收到的消息,其中subscribe表示已经成功订阅了某个频道。
命令:subscriber 频道
3、订阅模式
模式匹配功能允许客户端订阅符合某个模式的频道,Redis采用PSUBSCRIBE订阅符合某个模式所有频道,用“”表示模式,“ ”可以被任意值代替。
4、取消订阅
Redis采用UNSUBSCRIBE和PUNSUBSCRIBE命令取消订阅,其返回值与订阅类似。
由于Redis的订阅操作是阻塞式的,因此一旦客户端订阅了某个频道或模式,就将会一直处于订阅状态直到退出。在SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE和PUNSUBSCRIBE命令中,其返回值都包含了该客户端当前订阅的频道和模式的数量,当这个数量变为0时,该客户端会自动退出订阅状态。
六、redis的主从复制和哨兵模式
1、redis的主从复制(master/slave模式)
主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将数据同步给从数据库。而一般情况下,从数据库是只读的,并接收主数据库同步过来的数据。 一个主数据库可以有多个从数据库。
配置
准备两台服务器,分别安装redis , server1 server2
1. 在server2的redis.conf文件中增加 slaveof server1-ip 6379 、 同时将bindip注释掉,允许所有ip访问。(默认为主数据库)
2. 启动server1,server2
3. 访问server2的redis客户端,输入 INFO replication(查看节点状态信息)
4. 通过在master机器上输入命令,比如set foo bar 、 在slave服务器就能看到该值已经同步过来了。
原理
1、全量复制
master/slave 复制策略是采用乐观复制,也就是说可以容忍在一定时间内master/slave数据的内容是不同的,但是两者的数据会最终同步。具体来说,redis的主从同步过程本身是异步的,意味着master执行完客户端请求的命令后会立即返回结果给客户端,然后以异步的方式把命令同步给slave。这一特征保证启用master/slave 后 master的性能不会受到影响。
2、增量复制
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。master node会在内存中创建一个backlog,master和slave都会保存一个replica offffset还有一个master id,offffset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offffset开始继续复制但是如果没有找到对应的offffset,那么就会执行一次全量同步。
2、哨兵机制
在前面讲的master/slave模式,在一个典型的一主多从的系统中,slave在整个体系中起到了数据冗余备份和读写分离的作用。当master遇到异常终端后,需要从slave中选举一个新的master继续对外提供服务,redis并没有提供自动master选举功能,而是需要借助一个哨兵来进行监控。
什么是哨兵
哨兵是一个独立的进程,它的作用就是监控Redis系统的运行状况,使用哨兵后的架构图:
功能:
1. 监控master和slave是否正常运行。
2. master出现故障时自动将slave数据库升级为master
哨兵单点问题
为了解决master选举问题,又引出了一个单点问题,也就是哨兵的可用性如何解决,在一个一主多从的Redis系统中,可以使用多个哨兵进行监控任务以保证系统足够稳定。此时哨兵不仅会监控master和slave,同时还会互相监控;这种方式称为哨兵集群,哨兵集群需要解决故障发现和master决策的协商机制问题。
sentinel之间的相互感知
sentinel节点之间会因为共同监视同一个master从而产生了关联,一个新加入的sentinel节点需要和其他监视相同master节点的sentinel相互感知:
1. 需要相互感知的sentinel都向他们共同监视的master节点订阅channel:sentinel:hello。
2. 新加入的sentinel节点向这个channel发布一条消息,包含自己本身的信息,这样订阅了这个channel的sentinel就可以发现这个新的sentinel。
3. 新加入得sentinel和其他sentinel节点建立长连接。
master的故障发现
哨兵监控一个系统时,只需要配置监控master即可,哨兵会自动发现所有slave;这时候,我们把master关闭,等待指定时间后(默认是30秒),会自动进行切换。sentinel节点会定期向master节点发送心跳包来判断存活状态,一旦master节点没有正确响应,sentinel会把master设置为“主观不可用状态”,然后它会把“主观不可用”发送给其他所有的sentinel节点去确认,当确认的sentinel节点数大于>quorum时,则会认为master是“客观不可用”,接着就开始进入选举新的master流程;但是这里又会遇到一个问题,就是sentinel中,本身是一个集群,如果多个节点同时发现master节点达到客观不可用状态,那谁来决策选择哪个节点作为master呢?这个时候就需要从sentinel集群中选择一个leader来做决策。而这里用到了一致性算法Raft算法、它和Paxos算法类似,都是分布式一致性算法。但是它比Paxos算法要更容易理解;Raft和Paxos算法一样,也是基于投票算法,只要保证过半数节点通过提议即可。
配置实现:
sentinel monitor mymaster 192.168.11.131 6379 1(sentinel monitor name ip port quorum 其中name表示要监控的master的名字,这个名字是自己定义。ip和port表示master的ip和端口号。 最后一个1表示最低通过票数,也就是说至少需要几个哨兵节点统一才可以。)
启动哨兵
redis-sentinel sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
七、缓存穿透和雪崩
1、什么是缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去数据库查询。一些恶意的请求会故意大量查询不存在的key,就会对数据库造成很大的压力。这就叫做缓存穿透
2、如何避免缓存穿透
①采用布隆过滤器,将所有可能存在的数据存到一个bitMap中,不存在的数据就会进行拦截。
②对查询结果为空的情况也进行缓存,缓存时间设置短一点,不超过5分钟。
3、缓存击穿
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。直接设为永不过期就好了,分布式锁不好用。
4、什么是缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
5、如何避免缓存雪崩
redis高可用,多增设几台redis,集群的搭建
限级降流,通过锁或者队列来控制读数据库写缓存的线程数量,比如某个key只允许一个线程查询数据和写缓存,其他线程等待
数据预热,正式发布之前,先把可能的数据预先访问一遍,在即将发生大并发访问之前手动触发加载缓存不同的key,设置不同的过期时间,然缓存失效的实际平均点。