Redis原理分析与应用

过期删除的原理

Redis 中的主键失效是如何实现的,即失效的主键是如何删除的?实际上,Redis 删除失效主键的方法主要有两 种:

     消极方法:在主键被访问时如果发现它已经失效,那么就删除它

      积极方法:周期性地从设置了失效时间的主键中选择一部分失效的主键删除
对于那些从未被查询的key,即便它们已经过期,被动方式也无法清除。因此Redis会周期性地随机测试一些key, 已过期的key将会被删掉。Redis每秒会进行10次操作,具体的流程:
 1. 随机测试 20 个带有timeout信息的key;

 2. 删除其中已经过期的key;

 3. 如果超过25%的key被删除,则重复执行步骤1;
这是一个简单的概率算法(trivial probabilistic algorithm),基于假设我们随机抽取的key代表了全部的key空间。

Redis发布订阅

       Redis提供了发布订阅功能,可以用于消息的传输,Redis提供了一组命令可以让开发者实现“发布/订阅”模式 (publish/subscribe) . 该模式同样可以实现进程间的消息传递,它的实现原理是发布/订阅模式包含两种角色,分别是发布者和订阅者。

      订阅者可以订阅一个或多个频道,而发布者可以向指定的 频道发送消息,所有订阅此频道的订阅者都会收到该消息发布者发布消息的命令是PUBLISH, 用法是 PUBLISH channel message 比如向channel.1发一条消息:hello PUBLISH channel.1 “hello”这样就实现了消息的发送,该命令的返回值表示接收到这条消息的订阅者数量。

     因为在执行这条命令的时候还没有 订阅者订阅该频道,所以返回为0. 另外值得注意的是消息发送出去不会持久化,如果发送之前没有订阅者,那么后续再有订阅者订阅该频道,之前的消息就收不到了订阅者订阅消息的命令是SUBSCRIBE channel [channel ...] 该命令同时可以订阅多个频道,比如订阅channel.1的频道。 SUBSCRIBE channel.1 执行SUBSCRIBE命令后客户端会进入订阅状态

结构图

      channel分两类,一个是普通channel、另一个是pattern channel(规则匹配), producer1发布了一条消息 【publish abc hello】,redis server发给abc这个普通channel上的所有订阅者,同时abc也匹配上了pattern channel的名字,所以这条消息也会同时发送给pattern channel *bc上的所有订阅者。

Redis的数据是如何持久化的?

       Redis支持两种方式的持久化,一种是RDB方式、另一种是AOF(append-only-file)方式。RDB会根据指定的规 则“定时”将内存中的数据存储在硬盘上,而AOF在每次执行命令后将命令本身记录下来。两种持久化方式可以单独 使用其中一种,也可以将这两种方式结合使用.

RDB方式

   当符合一定条件时,Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,等 到持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作 的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方 式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失
--fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和 原进程一致,但是是一个全新的进程,并作为原进程的子进程
Redis会在以下几种情况下对数据进行快照 
1. 根据配置规则进行自动快照(save 900 1, save 300,10 save 60 10000 每条规则按照或的关系) 
2. 用户执行SAVE或者GBSAVE命令(save redis 同步快照阻塞请求  bgsave 异步请求)
3. 执行FLUSHALL命令
4. 执行复制(replication)时

aof方式

    当使用Redis存储非临时数据时,一般需要打开AOF持久化来降低进程终止导致的数据丢失。AOF可以将Redis执行 的每一条写命令追加到硬盘文件中,这一过程会降低Redis的性能,但大部分情况下这个影响是能够接受的,另外 使用较快的硬盘可以提高AOF的性能。Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。

      Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前
数据集所需的最小命令集合。重写的流程是这样,主进程会fork一个子进程出来进行AOF重写,这个重写过程并不是基于原有的aof文件来做 的,而是有点类似于快照的方式,全量遍历内存中的数据,然后逐个序列到aof文件中。在fork子进程这个过程 中,服务端仍然可以对外提供服务,那这个时候重写的aof文件的数据和redis内存数据不一致了怎么办?不用担 心,这个过程中,主进程的数据更新操作,会缓存到aof_rewrite_buf中,也就是单独开辟一块缓存来存储重写期间 收到的命令,当子进程重写完以后再把缓存中的数据追加到新的aof文件。当所有的数据全部追加到新的aof文件中后,把新的aof文件重命名为,此后所有的操作都会被写入新的aof文件。如果在rewrite过程中出现故障,不会影响原来aof文件的正常工作,只有当rewrite完成后才会切换文件。因此这个 rewrite过程是比较可靠的。

Redis内存回收策略

    默认的策略为noeviction策略,当内存使用达到阈值的时候,所有引起申请内存的命令会报错

    allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 
    allkeys-random:随机移除某个key。
    volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰。
    volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。 
    volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰


Redis是单进程单线程?性能为什么这么快

       Redis采用了一种非常简单的做法,单线程来处理来自所有客户端的并发请求,Redis把任务封闭在一个线程中从而避免了线程安全问题;redis为什么是单线程?
        CPU并不是Redis的瓶颈所在,Redis的瓶颈主要在机器的内存和网络的带宽。那么Redis能不能处 理高并发请求呢?当然是可以的,至于怎么实现的,我们来具体了解一下。 【注意并发不等于并行,并发性I/O 流,意味着能够让一个计算单元来处理来自多个客户端的流请求。并行性,意味着服务器能够同时执行几个事情, 具有多个计算单元】

多路复用

     Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞 的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提 供服务,而 I/O 多路复用就是为了解决这个问题而出现的。

了解多路复用之前,先简单了解下几种I/O模型

(1)同步阻塞IO(Blocking IO):即传统的IO模型。
(2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。
(3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。
(4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。 
同步和异步、阻塞和非阻塞,到底是什么意思,感觉原理都差不多,我来简单解释一下 同步和异步,指的是用户线程和内核的交互方式 阻塞和非阻塞,指用户线程调用内核IO操作的方式是阻塞还是非阻塞
就像在Java中使用多线程做异步处理的概念,通过多线程去执行一个流程,主线程可以不用等待。而阻塞和非阻塞 我们可以理解为假如在同步流程或者异步流程中做IO操作,如果缓冲区数据还没准备好,IO的这个过程会阻塞。

在Redis中使用Lua脚本

      Redis中内嵌了对Lua环境的支持,允许开发者使用Lua语言编写脚本传到Redis中执行,Redis客户端可以使用Lua脚本,直接在服务端原子的执行多个Redis命令。

      使用脚本的好处:

      1. 减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行
      2. 原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无 需担心会出现竞态条件

Redis集群

      先来简单了解下redis中提供的集群策略, 虽然redis有持久化功能能够保障redis服务器宕机也能恢复并且只有少量 的数据损失,但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有备份也仍然不可避免 数据丢失的问题。在实际生产环境中,我们不可能只使用一台redis服务器作为我们的缓存服务器,必须要多台实现集群,避免出现 单点故障;

主从复制

     主从复制就是我们常见的master/slave模式, 主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将 数据同步给从数据库。而一般情况下,从数据库是只读的,并接收主数据库同步过来的数据。 一个主数据库可以有 多个从数据库

配置

     在redis中配置master/slave是非常容易的,只需要在从数据库的配置文件中加入slaveof 主数据库地址 端口。 而 master 数据库不需要做任何改变。

原理

全量复制

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤

    完成上面几个步骤后就完成了slave服务器数据初始化的所有操作,savle服务器此时可以接收来自用户的读请求。

    master/slave 复制策略是采用乐观复制,也就是说可以容忍在一定时间内master/slave数据的内容是不同的,但是 两者的数据会最终同步。具体来说,redis的主从同步过程本身是异步的,意味着master执行完客户端请求的命令 后会立即返回结果给客户端,然后异步的方式把命令同步给slave。

     这一特征保证启用master/slave后 master的性能不会受到影响。

     但是另一方面,如果在这个数据不一致的窗口期间,master/slave因为网络问题断开连接,而这个时候,master 是无法得知某个命令最终同步给了多少个slave数据库。不过redis提供了一个配置项来限制只有数据至少同步给多 少个slave的时候,master才是可写的:

    min-slaves-to-write 3 表示只有当3个或以上的slave连接到master,master才是可写的

    min-slaves-max-lag 10 表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave以断开

增量复制

     从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的 地方,继续复制下去,而不是从头开始复制一份master node会在内存中创建一个backlog,master和slave都会保存一个replica offset还有一个master id,offset 就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续 复制但是如果没有找到对应的offset,那么就会执行一次全量同步

哨兵机制

    redis并没有提供自动master选举功能,而是需要借助一个哨兵来进行监控。

  什么是哨兵

   顾名思义,哨兵的作用就是监控Redis系统的运行状况,它的功能包括两个

   1. 监控master和slave是否正常运行
   2. master出现故障时自动将slave数据库升级为master 哨兵是一个独立的进程,使用哨兵后的架构图

 

     为了解决master选举问题,又引出了一个单点问题,也就是哨兵的可用性如何解决,在一个一主多从的Redis系统 中,可以使用多个哨兵进行监控任务以保证系统足够稳定。此时哨兵不仅会监控master和slave,同时还会互相监 控;这种方式称为哨兵集群,哨兵集群需要解决故障发现、和master决策的协商机制问题

sentinel之间的相互感知

sentinel之间的相互感知 sentinel节点之间会因为共同监视同一个master从而产生了关联,一个新加入的sentinel节点需要和其他监视相同master节点的sentinel相互感知,首先
1. 需要相互感知的sentinel都向他们共同监视的master节点订阅channel:sentinel:hello
2. 新加入的sentinel节点向这个channel发布一条消息,包含自己本身的信息,这样订阅了这个channel的sentinel 就可以发现这个新的sentinel 
3. 新加入得sentinel和其他sentinel节点建立长连接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值