Redis 知识点整理

1. Redis 数据结构

  1. 主要的数据类型:

    • String(K-V): 单值,键值对,类似 Memcached, 比如配置,常量值,开关等等。
    • Hash: 一般是存储对象接口,key 是对象的标示,filed 是属性,value 是属性值。
    • Set: 集合,存放不重复的数据,求交集,统计不重复的量。
    • List: 链表,常用在消息队列,TimeLine.
    • SortedSet: 排名,需要根据 一个值来排序的场景,排行榜等。
  2. 扩展数据类型

    • Pub/Sub 简单的发布/订阅,当订阅的 key 的值有变化的时候,会通知到订阅的客户端,回调。
    • HyperLogLog: 基数统计(B 树,bitmap,概率算法(LC,LLC,HLL)),统计一个大的集合(可能出现重复数据)中不同元素的个数。比如网站的 UV,链接访问的 UV,以及做合并的功能,还有留存。
    • Geo 地址位置信息
  3. Redis Module : Redis 拓展模块

    • BloomFilter: 布隆过滤器,快速判断一个元素是否在集合中。

      1. 就是一个很长的二进制 bit 位的数组,全部初始化为 0.
      2. K 个 hash 函数,每个 hash 函数会生成一个 hash 值。这个 hash 值对应了二进制 数组的某个点,然后将这个点标记为 1.
      3. 查询一个数据存在不存在时,需要判断 这 K 个点的位置是否都未为 1.
      4. 布隆过滤器添加元素
        1. 将要添加的元素给k个哈希函数
        2. 得到对应于位数组上的k个位置
        3. 将这k个位置设为1
      5. 布隆过滤器查询元素
        1. 将要查询的元素给k个哈希函数
        2. 得到对应于位数组上的k个位置
        3. 如果k个位置有一个为0,则肯定不在集合中
        4. 如果k个位置全部为1,则可能在集合中
      6. 优点: 是占用空间小,效率高。
      7. 缺点: 有误判,不允许删除。如果需要删除,可以CBF,每一位是一个 counter,不再是0和1两种结果。
    • RedisSearch

    • Redis-ML,

2. Redis 分布式锁

  1. setnx抢锁,然后设置一个 过期时间。不能先 set 抢锁,再 expire,必须保证原子性。
    • spring-data-redis:2.1版本后,使用 setIfAbsent(K key, V value, long timeout, TimeUnit unit) 方法来实现。

3. Redis 查找指定格式的 key

  1. 如果使用 keys ,但是会卡住 redis,因为 redis 是单线程的。所以可以用 scan,但是会有重复,需要客户端做一次去重复。

4. Redis 做异步队列

  1. 一般用 list 作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有消息的时候,适当的 sleep 一定的时间再重试,如果不用 sleep。可以用 blpop 命令,如果没有消息,会一直阻塞到消息来为止。
  2. 通过 pub/sub 订阅者模式 来做一次生产,多次消费,可以实现 1:N 的消息队列。pub/sub 的缺点是,在消费者下线过后,生产的消息会丢失,如果需要保证不丢失,需要使用 MQ.
  3. redis 实现延时队列,用时间戳做 score,消息内容做 member, 然后通过 ZADD 添加消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询处理。不过不建议,太占用内容。队列还是建议使用 MQ, Kafka

5. key 的过期时间

  1. 如果有大量的 key 在同一个时间过期,防止 redis 暂时的卡顿,在时间上面加一个随机值,使得过期时间分散一些。

6. Redis 持久化

  1. http://oldblog.antirez.com/post/redis-persistence-demystified.html
  2. 持久化方式:
    1. RDB 指定间隔时间的某个时间点的快照。
    2. AOF 持久化操作日志。当 redis 重启的时候,需要根据 AOF 的 log 文件来重构数据。AOF 日志文件是redis 的自定义格式。当 AOF文件太大,redis 会重写该日志文件,减少命令数,但是结果一致。比如多次累加一个 key 100次。aof 就会有100条语句,BGREWRITEAOF会精简命令。
    3. 可以禁用 redis 的持久化,只要我们想让我们的数据只在 redis 运行时存在。
    4. 可以同时使用 AOF 和 RDB 来持久化 redis 中的数据。需要注意的是,此时,Redis 重启时,AOF 的日志文件会被用来重构 redis 中的数据,以此来保证数据的完整性。
  3. RDB 做全量持久化,AOF 做增量持久化。RDB 每次消耗的时间长,down 机时,会丢失两次持久化之间的数据。所以,需要配合 AOF 来使用。Redis 重启时,先用 RDB 持久化的文件重构内存,然后使用 AOF 回放最近的操作指令来实现完整恢复重启之前的状态。
  4. 对于突然断电的结果,取决于 AOF 刷新日志到磁盘的时间间隔 sync。建议是 1s 刷新一次。
  5. RDB 的原理,就是 fork & COW. fork 过后,子进程和父进程共享数据段,此时,可以看做没有占用额外的内存开销。当父进程的数据有修改时,才会复制一份到子进程保存。所以,只有在极限情况,所有的父进程数据有修改,及其的物理内存使用率才会是 50%。
  6. RDB 的优点是重启快,缺点是会丢失数据,备份一次的时间长。AOF 的优点是可以做到不丢失数据或者丢失很少的数据,但是重启很慢,因为需要重新根据日志来构建 redis 数据。所以往往是 RDB 和 AOF 搭配使用。

7. Pipline

  1. Pipline 的好处是可以将多次 IO 减少为 1次。前提是这些之类之间没有因果相关性

8. Redis 的同步机制

  1. Redis 可以使用主从同步,从从同步。
  2. 启动时,做第一次同步,主节点做一次 rdb,同时将后续修改操作放入 buffer,待 rdb 完成后。将 rdb 文件全量同步到 从节点,从节点接受完成后讲 rdb 镜像加载到内存。加载完成后,再通知主节点讲期间修改的 缓存 buffer 发送过来。
  3. 以上是第一次启动时候的同步,当机器都启动完成后,后面通过 AOF 做同步就是近乎实时。

9. Redis 集群

Redis-sentinal 是着眼于高可用性。在 master down 机时,能在 slave 中选举一个新的 master,继续提供服务。
Redis-cluster 着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

  1. redis 集群的 键分布模型,

    • 采用的 一种 hash slot(hash槽) 的 sharding 方式,而不是一致性 hash
    • Redis 集群的键空间被分割为 16384 个槽(slot), 集群的最大节点数量也是 16384 个,推荐的最大节点数量为 1000 个左右。
    • 每个主节点都负责处理 16384 个槽中的一部分。
    • 使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽
    • 删除某个节点:只需要将删除的节点中的槽移动到其它的节点,然后再移除空白槽需要删除的节点。
    • 增加一个节点:只需要将当前所有节点中的某些槽移动到新的节点。
  2. 因为将一个 hash 槽从一个节点移动到另一个节点,不会造成节点堵塞,所以无论是添加还是移除已经存在的节点,又或者改变某个节点包含的 hash 槽数,不会造成集群下线。

  3. Redis 集群不保证数据的强一致性(strong consistency): 在特定条件下, Redis 集群可能会丢失已经被执行过的写命令。

10. Redis 集群搭建

11. 参考

https://zhuanlan.zhihu.com/p/32540678
http://blog.codinglabs.org/articles/algorithms-for-cardinality-estimation-part-i.html
https://bindog.github.io/blog/2015/02/14/cardinality-counting/
https://blog.csdn.net/firenet1/article/details/77247649

Just for my love !!