Redis 要点

  • 资料来源于网络。
  • Redis是一个开源的、由C语言编写的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。
  • 常用数据类型有hash、string、list、set、sortedset,Key-Value形式,其中Key一定是string。

数据类型底层

string -> SDS -> set,get,decr,incr,mget

hash -> ziplist/hashtable -> hget,hset,hgetall

list -> ziplist/linkedlist -> lpush,rpush,lpop,rpop,lrange

set -> intset/hashtable -> sadd,spop,smembers,sunion

zset -> ziplist/skiplist -> zadd,zrange,zrem,zcard

简单动态字符串 SDS

char buf[]; //字节数组

int len; //字符串长度

int free; //未使用长度

哈希表 hashtable

  • dict 结构内部包含两个 hashtable,通常情况下只有一个 hashtable 是有值的,数据结构类似于Java的hashmap。
  • 但是在 dict 扩容缩容时,需要分配新的 hashtable,然后进行渐进式搬迁/渐进式rehash,这时候两个 hashtable 存储的分别是旧的 hashtable 和新的 hashtable。待搬迁结束后,旧的 hashtable 被删除,新的 hashtable 取而代之。
  • Redis 的字典默认的 hash 函数是 siphash

压缩列表 ziplist

  • 压缩列表是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。
  • hash中K、V紧挨着排列。
  • zset中V、score紧挨着排列。

双向链表 linkedlist

  • 普通的双向链表。

小整数集合 intset

  • intset始终保持从小到大有序。

跳跃链表 skiplist

  • 拔高某一部分,形成一个新的链表结构,便于查找。

优点

  • 纯内存操作。
  • 单线程,避免了上下文切换
  • 非阻塞I/O多路复用机制/事件驱动。

问题

缓存雪崩

缓存数据设置的过期时间相同,且Redis将这部分数据全部删光了。这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。

缓存穿透

缓存穿透是指查询一个一定不存在的数据。由于缓存不命中,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。

缓存、数据库双写一致

  • 先更新数据库 再删除缓存
  • 先删除缓存 再更新数据库

过期策略

  • 定时删除
    • 到时间点上就把所有过期的键删除了。
  • 惰性删除 - Redis使用
    • 每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。
  • 定期删除 - Redis使用
    • 每隔一段时间去删除过期键,限制删除的执行时长和频率。

持久化方式

  • RDB(基于快照),将某一时刻的所有数据保存到一个RDB文件中。
  • AOF(append-only-file 文件追加),当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。

RDB

  • SAVE会阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止。
  • BGSAVE创建出一个子进程负责创建RDB文件,已过期的键不会保存在RDB文件中

AOF重写

  • AOF重写由Redis自行触发,在后台子进程进行。
  • AOF重写不需要读取现有的AOF文件,AOF重写是通过读取服务器当前数据库的数据来实现的。

内存淘汰机制

机制名称 挑选集合 挑选策略
volatile-lru 从已设置过期时间数据集中 最近最少使用
volatile-ttl 从已设置过期时间数据集中 最接近过期时间
volatile-random 从已设置过期时间数据集中 随机
allkeys-lru 从所有数据集中 最近最少使用
allkeys-random 从所有数据集中 随机
noeviction 禁止淘汰数据 禁止淘汰数据

Redis 集群

主从架构

特点

  • 服务器负责接收请求
  • 服务器负责接收请求
  • 从服务器的数据由主服务器复制过去。主从服务器的数据是一致

优势

  • 读写分离(主服务器负责写,从服务器负责读)
  • 高可用(某一台从服务器挂了,其他从服务器还能继续接收请求,不影响服务)
  • 处理更多的并发量(每台从服务器都可以接收读请求读QPS就上去了)

主从复制

  • 同步(sync)

    • 将从服务器的数据库状态更新至主服务器的数据库状态
  • 命令传播(command propagate)

    • 主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致,让主从服务器的数据库状态重新回到一致状态

哨兵机制(Sentinel)

  • 如果主服务器挂了,我们可以将从服务器升级为主服务器,等到旧的主服务器重连上来,会将它变成从服务器
  • 过程称为主备切换/故障转移,用于实现Redis的高可用性