Redis中的常用数据结构

Redis中的常用数据结构

2019, Aug 19    

前言

Redis在曾经实现用户登录token的时候使用过,但是对其的了解程度,就只是在使用的这个层次。本篇文章主要用于学习记录Redis的常见的一些数据结构。

第一部分 什么是redis?

  • 是NoSql数据库,非关系型数据库。
  • 是个非关系型数据库。
  • Key-Value数据库
  • 使用C语言实现的单线程应用,基于内存,读取的速度都超快!
  • 基于内存存放,使用了rdb (就是redis内存的SNAPSHOT,存到了磁盘当中)和Aof(Append only file 也就是平时操作的命令集合)的机制来保障数据的持久化,宕机的时候可以通过这两种方式来进行数据恢复。
  • 拥有丰富的Value对象,String\Hash\List\Set\ZSet\Stream
  • 拥有多种底层数据结构:SDS,list,dict,zskiplist,intset,ziplist,quicklist,zipmap,stream
  • 支持丰富功能,过期,事物

第二部分 常用Value对象

1 String对象

最常见的类型

1.1 编码

int,可以自增 embstr,就是单纯的字符串 raw

1.2 扩容长度

字符串在小于1M的时候,是加倍扩张的策略 在超过1M的时候,每次扩容会增加1M的空间,每个key最大512M

2 List

相当于java中的linkedList 插入和删除非常快,时间复杂度是O(1)

2.1 编码

redis3.2之后列表的内部实现变成了quickList而非传统的ziplist或者双向链表实现。使用的是quicklist和ziplist组成的双向链表。 ziplist的分配过长和过小都不好,过小了会太多碎片化,过大了之后空间复杂度就会更大。

list-max-ziplist-size-2可以用来设置size. list-compress-depth 0:表示数据都不被压缩,为n的话,就是两端的n个数据不被压缩,双向链表

2.2 常用场景

消息队列

3 Hash

3.1 编码

zipList 默认,所有的key value,长度都小于64,保存的键值对数量都小于512 ht(hashTable),超过了就用ht

4 Set和ZSet

Set无序和唯一的 ZSet是可排序的,是对每一个元素添加了一个分数一样的东西

4.1 编码

Set 小512用intset,大于用hashtable ZSet 小64数量小128 用ziplist 否则用skiplist

4.2 场景

跟踪唯一性数据,比如说排行榜

5 stream

  • 是redis5.0 后引入的一种新数据类型。
  • Stream的多个客户端是竞争关系,可以拿到以前的数据,是通过id来获取的,stream会永久的存储数据 和KafKa的机制很类似。

  • 提供了消费者组,不同组接受到的数据一致,组内是竞争关系。 可以设置为阻塞和非阻塞的

类型和编码的对应关系,是在redisObject这个类中进行存储的

第三部分 底层数据结构

1 dict字典

底层实现

扩容和缩容是根据负载因子的值来做的

  • used/size
  • 如果大于1 且没有备份
  • 如果大于5 且在备份 那么就扩容,如果小于0.1那么来进行缩容
  1. h1设置为扩容缩容所需要设置的大小
  2. h0rehash放入h1当中,释放h0,给h1改名
  3. 不会锁主线程,会在每次的操作的过程中,做一次渐进的hash的过程

2 ziplist

是redis为了节约内存而进行开发的 是由一系列的特殊编码的连续内存块所组成的顺序形数据结构

第四部分 其他事件

  1. 过期操作
    • 定时删除策略
    • 惰性删除策略
    • 定期删除策略,每段时间删除一批,但是不会全量的删除
  2. 内存淘汰机制
    • noeviction
    • allkeys-lru
    • allkeys-random
    • volatile-lru
    • volatile-random
    • volatile-ttl