前言
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那么来进行缩容
- h1设置为扩容缩容所需要设置的大小
- h0rehash放入h1当中,释放h0,给h1改名
- 不会锁主线程,会在每次的操作的过程中,做一次渐进的hash的过程
2 ziplist
是redis为了节约内存而进行开发的 是由一系列的特殊编码的连续内存块所组成的顺序形数据结构
第四部分 其他事件
- 过期操作
- 定时删除策略
- 惰性删除策略
- 定期删除策略,每段时间删除一批,但是不会全量的删除
- 内存淘汰机制
- noeviction
- allkeys-lru
- allkeys-random
- volatile-lru
- volatile-random
- volatile-ttl