Redis初识

什么是Redis

Redis是一个开源的,基于内存的存储系统。它可以用作数据库、缓存和消息中间。它支持多种数据结构,如字符串(String)、散列(Hash)、列表(List)、集合(Set)、有序集合(ZSet)、位图(BitMap)、地理空间(Geo)、HyperLogLog。Redis内置了复制(Replication)、LUA脚本、LRU驱动事件、事务以及不同级别的磁盘持久化模式,并且可通过哨兵和分区提供高可用特性。

Redis有哪些优点,为什么要用 Redis?

  • 内部支持多种数据结构,能够很好的帮助我们解决在不同业务场景中出现的各类问题,如:
    • String: 缓存字符串、计数器、id生成器等。
    • Hash: 缓存结构化对象
    • List: 缓存对象集合、实现分布式双端队列
    • Set: 去重、共同好友、抽奖
    • ZSet: 动态排行、延迟队列
    • BitMap: 布隆过滤器
    • Geo: 缓存地理坐标
    • HyperLogLog: 提供不精确的去重计数方案,可用于点赞数统计
  • 高性能,基于内存和IO多路复用使得Redis具备优秀的读写性能和高并发支持,支持集群部署进一步提高存储服务的吞吐量。
  • 高可用,基于哨兵模式的主从部署。
  • 支持Lua脚本,我们可以吧多个Redis指令写到一个Lua脚本中执行以保证原子性。
  • 支持数据持久化,防止服务宕机时内存数据丢失,有利于故障恢复。
  • 支持事务。

Redis 的持久化机制有哪些?

Redis提供两种持久化方案分别是RDB和AOF

  • RDB(Redis DataBase):周期性的将内存中的数据制作成快照写到磁盘中,数据恢复时将快照文件直接读到内存里,通过fork子进程来完成,不会导致主进程阻塞。
    • 优点:适合大规模的数据恢复,对数据完整性和一致性要求不高的情况。
    • 缺点:服务down机后会丢失最后一次快照后的所有修改;fork的时候内存数据被克隆了一份,需要考虑大致两倍的膨胀。
  • AOF:将所有写指令记录到aof文件中,当Redis服务重启时会将aof文件中的命令重新执行以恢复数据,AOF写入时机有三种模式,always(每次数据修改都会写一次aof)、eversec(每秒执行一次写入)、no(由Redis自己决定写入时机,通常会在空闲时写入)。
    • 优点:适用于对数据完整性和一致性要求较高的场景。
    • 缺点:AOF通常对磁盘空间占用较大;数据恢复相对于RDB要慢很多。

      如上图所示,其流程如下:
      • 所有的写命令会先追加到aof缓冲中
      • AOF缓冲区根据对应的策略向磁盘进行写入
      • 随着AOF文件大小到达一定阈值时需要执行rewrite操作达到压缩的目的
      • 当Redis重启时,可以通过AOF文件进行数据恢复
  • RDB&AOF混合模式:Redis 4.0后支持的一种新的持久化模式,其目的是为了解决单一使用RDB或AOF持久化模式时产生的问题。当开启混合持久化模式时fork出的子进程先将内存数据以RDB的方式写入AOF文件,然后再将AOF缓冲中的增量命令以AOF方式写入到文件,写入完成后通知祝进程更新统计信息,并将旧的AOF文件替换为新的。在Redis重启后通过AOF文件进行数据恢复,先加载RDB内容再加载剩余的AOF内容。

Redis过期键的淘汰机制

Redis针对键的淘汰策略有:

  • 针对所有key
    • allkeys-lru:当内存不足以容纳新写入的数据时,在键空间中移除最近最少使用的key。
    • allkeys-random:当内存不足以容纳新写入的数据时,在键空间中随机移除某个key。
    • noeviction:当内存不足以容纳新写入的数据时,新写入命令会报错。
  • 仅针对有过期时间的key
    • volatile-lru:当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中移除最近最少使用的key。
    • volatile-random:当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中随机移除某个key。
    • volatile-ttl:当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

Redis针对过期键的淘汰时机:

  • 实时过期:为每个key设置一个定时器实现实时的自动过期,该策略对内存较友好,但会占用大量的CPU资源。
  • 惰性过期:每当访问一个key时才会判断是否过期,过期则删除并返回null,该策略对cpu较友好,但会可能会存在大量过期数据占用内存资源的情况。
  • 定时过期:每隔一定时间扫描一定数量的过期键将其删除,该策略是已上两种策略的一种折中方案,以达到cpu和内存使用的平衡。

Redis中使用了惰性+定时两种过期策略

Redis的线程模型

Redis内部实现了一个网络事件处理器,它由多路复用器,fd(套接字的文件描述符)事件分配器、df事件处理器以及多个套接字组成。服务端用于监听用的套接字和与服务端建立链接后负责与客户端通信用的套接字会交由多路复用器进行监听,多路复用器筛选出产生事件的套接字fd事件交给fd事件分配器进行分配,事件分配器根据事件类型将fd事件分配给相应的fd事件处理器执行,fd事件非配和执行都在主线程中进行的,因此Redis执行用户命令采用的是单线程模型。

应避免在redis中执行耗时操作如keys,这会导致后面的执行被阻塞。

I/O多路复用

一个I/O操作在OS中的的完整流程是数据请求先从用户态到内核态,通过OS提供的api调用相应的设备去获取数据,当设备准备好数据后数据被复制到内核态,最后将数据从内核态再复制到用户态中。

数据从硬件到内核态的过程可以有阻塞或非阻塞两种方式

  • 阻塞:用户请求会等待数据准备好后从设备返回到内核态,整个过程处于一个阻塞的状态。
  • 非阻塞:非阻塞时不管设备是否准备好数据都返回一个对应的文件描述符到内核态中。

数据从内核态到用户态的处理方式可以分为同步或异步

  • 同步:用户态处于阻塞状态,期间不能做其他操作
  • 异步:用户态在等待数据返回的同时可以做其他操作

多路复用采用指数据从设备复制到内核态使用非阻塞模式,常见的多路复用模型有:select、poll、epoll。

  • select/poll:调用内核api,将fd集合从用户态传入内核态中,由内核执行遍历筛选出已经准备好数据的fd集合返回给用户态,这两种模型存在以下缺陷:
    • 每次都需要将fd集合从用户态传入到内核态,产生I/O开销。
    • 每次都需要在内核中遍历fd集合,当fd集合很大时会占用过多的cpu资源。
    • 对传入fd集合大小有限制,当集合过大时需要分批传入。
  • epoll:与select和poll不同,当采用epoll模型是,内核中会维护一个eventpoll结构体,它主要由红黑树rb和链表rdlist组成,当内核态向网卡请求数据时将产生一个epitem保存在eventpoll结构的rb中并与网卡建立回调关系,网卡产生事件时通过回调将rb中对应的epitem加入到rdlist中并标记事件类型。每当用户态调用epoll_wait方法时只需要将rdlist返回即可。eventpoll结构如下:
struct eventpoll{
  
  // 红黑树,用于存放需要监控的fd事件,与网卡建立了回调关系,当网卡产生事件时(建立链接、数据写入)
  struct rb_root rb;
  // 双向链表,存储着返回通过epoll_wait返回给用户态满足条件的事件
  struct list_head rdlist;
}

// rb/rdlist 中存储的事件结构
struct epitem {
   
  // 文件描述符
  struct epoll_field fd 
  // 事件类型
  struct epoll_event event
}

epoll相比select和poll,省去了fd集合从用户态传入内核态的I/O开销以及在内核态中遍历fd集合的操作降低了cpu使用的开销。

Redis中的事务

Redis的事务本质是Muti、Exec、Watch和DISCARD等一组命令的集合,支持一次执行多个命令,一个事务中所有命令会预先加入到代执行队列中,在事务的执行过程中按顺序执行队列中的命令。

Redis事务对ACID的支持
  • A(原子性):Redis的事务并不支持回滚,其理念是运行时出错的语句单个报错即可,其他的正常运行,其实现的是自己所认为的原子性。
  • C(一致性):一致性指A状态经过事务变为B状态后不破坏原有约束,Redis天然支持。
  • I(隔离性):Redis处理客户命令采用的是单线程模型,天生具备隔离性。
  • D(持久性):当Redis运行在AOF持久化模式下时,Redis事务具备部分持久性。

哨兵模式

Redis可通过哨兵模式大健主从模式实现高可用,哨兵本身也是一个Redis节点,区别是它不做数据存储,其主要功能如下:

  • 故障转移:如果master节点挂了会从slave节点中选举一个作为新的master。
  • 节点监控:监控每隔节点是否正常工作。
  • 告警:节点出现故障时通报管理员。

哨兵用于实现Redis的高可用,本身也是分布式的作为一个哨兵集群去运行,互相协同工作。进行故障转移时需要过半通过后才能选举出新的master,这涉及到分布式选举问题,常见的选举算法有(Raft、Paxos、Zab等),Redis采用的是Raft算法(raft详见http://thesecretlivesofdata.com/raft/)。

Redis主从复制

Redis的主从复制可分为全量同步和增量同步:

  • 全量复制:当slave节点启动时会发送一个psync命令给master节点,如果时初次链接到master节点会触发一次全量复制,master会开启后台线程生成rdb快照发送给slave,slave会先将rdb文件写入磁盘后在将其加载进内存,接着master会把制作快照后发生的数据变化发送给slave进行同步
  • 增量复制:Redis增量复制是指slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

Redis集群

Redis官方提供了集群部署方案Redis Cluster,它是一种服务端Sharding技术,3.0版本开始正式支持。它采用的是采用slot(槽)的概念,一共分成16384个槽,通过哈希的方式,将数据分片,每个节点均分存储一定哈希槽(哈希值)区间的数据,每份数据分片可存储在多个互为主从的多节点上。客户端请求可发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行。

采用slot分片的优缺点:

  • 优点
    • 无中心架构,支持动态扩容,对业务透明
    • 具备Sentinel的监控和自动Failover(故障转移)能力
    • 客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值