Redis入门基础知识

Redis

  1. 简介:redis 全称remote dictionary server,是用c语言编写的内存高速缓存数据库,基于key-value存储系统,支持的数据类型包括string、list、hash、set和zset;

  2. 应用场景:

  • 缓存(redis支持事务性的批量原子操作,可保持数据一致性)
  • 延时任务(缓存设置过期时间,可用于优惠券、限时验证码等业务)
  • 计时器场景(可以实现原子的自增,用于高并发的秒杀,限制接口的请求调用等场景)
  • 分布式锁(设置一个键值,通过过期时间避免持有锁的应用宕机导致的死锁,通过redis集群避免redis宕机产生的死锁,通过设置键的特定值来避免持有锁的应用由于执行超时导致将新锁的键值误删,通过刷新过期时间为不限时的锁应用服务,用于秒杀系统等)
  • 延时操作(设置一个限时键值,利用redis的发布与订阅机制,监控key的失效后启动相关的逻辑,例如订单失效后库存的恢复);
  1. 数据类型:
    5种基础类型。
    在这里插入图片描述
    3种特殊类型:
  • HyperLogLogs(基数统计):这个结构可以非常省内存的去统计各种计数,比如注册 IP 数、每日访问 IP 数、页面实时UV、在线用户数,共同好友数等。HyperLogLog 在 Redis 中每个键占用的内容都是 12K,理论存储近似接近 2^64 个值,不管存储的内容是什么,它一个基于基数估算的算法,只能比较准确的估算出基数,可以使用少量固定的内存去存储并识别集合中的唯一元素,而且这个估算的基数并不一定准确,是一个带有 0.81% 标准错误的近似值(对于可以接受一定容错的业务场景,比如IP数统计,UV等,是可以忽略不计的)。
  • Bitmap (位存储):位图数据结构,都是操作二进制位来进行记录,只有0 和 1 两个状态。比如:统计用户信息,活跃,不活跃! 登录,未登录! 打卡,不打卡! 两个状态的,都可以使用 Bitmaps! 如果存储一年的打卡状态需要多少内存呢? 365 天 = 365 bit 共 46 个字节左右!
  • geospatial (地理位置):这个功能可以推算地理位置的信息: 两地之间的距离, 方圆几里的人。
    流类型:
  • stream类型:
    该类型是Redis对消息队列的完善实现。以往的消息队列可以使用发布订阅机制,但其缺点在于无法持久化,可能由于服务宕机而丢失消息。或者使用list或者zset来持久化,但无法实现多播和分组消费。
    stram详解
    stream的结构:
    在这里插入图片描述
    分布式ID中包含时间戳部分,为了避免服务器时间回拨带来的问题,Redis的每个Stream类型数据都维护一个latest_generated_id属性,用于记录最后一个消息的ID。若发现当前时间戳退后(小于latest_generated_id所记录的),则采用时间戳不变而序号递增的方案来作为新消息ID(这也是序号为什么使用int64的原因,保证有足够多的的序号),从而保证ID的单调递增性质。
  1. 持久化
  • RDB:Redis Database,存储当前的内存快照。

    • 手动存储:bgsave。开启一个子进程来将当前内存快照覆盖旧快照,为了避免服务器崩溃影响快照,总是将备份的临时数据完整后才覆盖旧快照。
    • 自动存储:1. 在配置文件可以设置M秒内N次修改时自动触发bgsave。主从之间全量复制时自动调用bgsave将快照发给从节点。备份期间基于copy-on-write的思想,在主进程修改内存数据时,会复制原有的数据到特殊区域,修改页表的物理地址指向然后再在主进程对内存修改,这样不会对子进程的快照产生影响。
  • AOF:写后日志,即先写内存再将其记录到日志中。
    每次执行写命令,都将其载入aof缓冲区。为了避免命令过多导致文件过大,redis会对aof中的冗余命令进行重写,瘦身文件。具体为:主线程fork一个bgrewriteaof子进程,主进程将内存拷贝一份给子进程,子进程根据内存生成写操作到新的日志中。如果此时有新数据写入,先写到一个缓冲区,然后在子进程重写完成后添加到重写的日志中。

  • 两种方式在宕机时都是使用的旧文件,在fork子进程时为了避免同时一次性大量拷贝内存,子进程拷贝的是父进程的页表,修改时父进程拷贝内存并修改其页表的指向,从而不影响子进程快照。

  • 两种方式混合:为了避免频繁rdb的快照存储导致的fork阻塞和额外开销,可以使用aof记录快照之间的操作。既避免了大文件,也避免了重写日志。

  1. 发布与订阅:
    客户端订阅任意数量的频道,每当有消息发布到频道,就会被发送到订阅了频道的客户端。此外,模式代表了多个具有指定的相似名称的频道,订阅模式可以同时订阅这些匹配的频道。基于频道的发布与订阅是基于字典实现的,键为频道值为客户端组成的链表。订阅和退订就是添加和删除节点的过程。

  2. 事件机制:只关注网络IO和定时器。

  • 文件事件:处理redis服务器与客户端之间的网络IO,使用单线程的IO多路复用监听多个套接字,并为套接字的不同请求关联到相应的处理操作;
  • 时间事件:用于处理定时操作,所有的时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。
  • aeEventLoop是整个事件驱动的核心,它管理着文件事件表和时间事件列表,不断地循环处理着就绪的文件事件和到期的时间事件。在这里插入图片描述
  1. 事务机制:
    本质是一组命令的集合,一个事务中的命令会被序列化,放在一个事务队列中,一次性、顺序的、排他的执行。其他事务的命令不能插入其中。
  • watch为事务提供cas行为:在开启事务multi之前,使用watch监听需要操作的键值对。在事务提交时会检查监听的键值与当前值比对,不同则取消执行当前事务实现回滚,并取消watch,否则执行所以事务操作。
  • redis事务支持编译时错误的不执行,但并不支持运行时错误的回滚,而是继续执行余下的命令。因为运行时错误是编程的错误,不管是否回滚都不能纠正这类错误。
  • redis的ACID:不保证原子性,事务操作要么全部执行要么全部失败,运行错误只会跳过而非回滚;
    • 不保证一致性:watch命令失败可以取消不执行,但运行失败的命令会导致不一致性;
    • 保证隔离性:因为redis是单进程单线程模式的,其事务操作不被其他客户端命令打断。同时其不具备隔离级别;
    • 不保证持久性:因为rdb和aof都是异步执行的,宕机会造成数据丢失。
  1. 主从复制:将主服务器的数据复制到从服务器,复制只能单向。实现了数据的热备份、主服务器的快速恢复、主写从读的负载均衡。在这里插入图片描述
    全量复制的三个阶段:第一次主从同步之间实行。在这里插入图片描述
    增量复制:主从网络断开之后执行。
    在这里插入图片描述
  2. 哨兵机制:
    在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制,它有效地解决了主从复制模式下故障转移的问题。它提供了这些功能:
  • 监控主从节点是否运行正常,在主节点失效时选择一个从节点作为新的主节点;
  • 客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址;
  • 哨兵将故障转移的结果发送给客户端。哨兵集群通过发布与订阅模型构建。在主从集群中,主库上有一个名为__sentinel__:hello的频道,不同哨兵就是通过它来相互发现,建立连接和互相通信的。
  • 此外,哨兵通过主库获取从库信息并分别与之建立连接。每个哨兵可以发起主库下线的投票,哨兵投票超过配置的票数则进行新主库的选举,新主库偏向于在线且复制最完整的从库。
  1. 分片技术:
    主从复制扩展了主库的读能力,但其写能力和存储能力的扩展只能通过主库集群及其对应从节点来完成。
  • 分片技术将数据分散到不同的节点群(利用crc16校验算法后与2^14-1取模。因为心跳会携带所有slot信息,虽然crc16可以提高2 ^ 16个槽,但节点数量一般不超过1000,因此使用2 ^14个槽足够了并且可以在心跳传输时被压缩到2k)。
  • 可以自定义每个主节点的哈希槽数量,因此对扩展性友好。
  • 集群中每个节点都有唯一标识的id用于标记节点,节点间会保留其他节点的信息和TCP连接在查询键值对时,可以任意访问节点,该节点计算对应的哈希槽和节点后选择返回值(slot在当前节点),Moved重定向(slot不在当前节点)或者ASK重定向(slot正在迁移)。这个过程可以由smart客户端简化,它管理key->slot->node缓存来加速查找和定位,如果对应节点正在迁移会将键值对应的新节点告知客户端以更新缓存。
  • 每个节点记录了当前集群的状态,包括各节点负责的slot、master-slave和存活状态。为了在新节点入群、slot迁移、节点宕机和slave提升master时尽快被集群意识到,心跳(ping\pong\meet)及其数据是维护集群状态的主要途径,其底层通讯为Gossip协议(不适用发布订阅模型是因为其采用广播机制会加重带宽的负担,而gossip使用逐渐告知的机制降低了带宽开销)。
  • 节点之间通过ping和pong将节点所知的部分节点状态进行交互,当某节点ping不通一个节点,会将该节点标记为预下线并告知其他节点,在后续通讯时节点会记录预下线节点的票数,当半数节点及当前节点认为其预下线时裁定为已下线并广播告知其他节点立刻将其标记为已下线。
  • 新节点入群时通过meet告知任一节点,该节点会返回其所知的其他节点信息,让新节点与其他节点通过meet建立连接,最终全体建立连接。
  • 广播只在告知节点已下线、slave提升为master和slot迁移等需要快速更新集群状态时使用。
  1. 一致性、穿透、雪崩、污染:
  • 缓存穿透是指对不存在的键值对的高并发请求。避免手段是对请求键过滤,例如校验和bloom,或者设置一个短期空缓存;
  • 缓存击穿是指对单个或多个键值对的高并发请求,缓存失效或不存在时高并发的请求会大大影响数据库。避免手段是设置热点数据不过期,或者为重要接口设置限流、熔断等降级服务,让多余的请求或不可用的服务接口设置熔断以快速失败返回。或者设置互斥锁,只让某个请求去回设缓存;
  • 缓存雪崩指大量键值对同时失效。避免方式是设置不同的过期时间,或者将热点数据均匀分布在不同数据库;
  • 缓存污染:不常使用的数据在存满时需要删除。
  • redis有八种策略:
    • noeviction(默认的,不删除缓存而是返回错误,故不能解决缓存污染)、
    • 四种策略从设置了过期时间的缓存淘汰
      • random:从设置时间的缓存中随机选择,无法甄别冷数据,不能解决污染;
      • ttl:选择过期时间最早的数据;
      • lru:选择最近最少使用的数据,每个缓存增加访问时间字段。随机选择数据集,淘汰其中访问时间戳最小的那个,避免维护全局访问链表;
      • lfu:选择最少使用的数据,在lru的基础上增加计数器字段,这个字段有8bit,为了控制增长到255的速度,通过配置增长系数来控制热数据的增长。优先比较计数其次时间。
    • 两种策略从全局的缓存淘汰
      • random:从全局数据随机选择淘汰;
      • lfu:从全局数据随机选择数据集。
  1. 面试集锦
    题目1
    题目2
  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值