Redis数据结构底层原理及Redis 6 特性

1.Redis 基本特性

  • 非关系型的键值对数据库,可以根据键以O(1) 的时间复杂度取出或插入关联值
  • 数据是存在内存中的
  • 键的类型可以是字符串,整型,浮点型等,且键是唯一的
  • 值类型可以是string,hash,list,set,sorted set 等
  • 内置了复制,磁盘持久化,LUA脚本,事务,SSL, ACLs,客户端缓存,客户端代理等功能
  • 通过Redis哨兵和Redis Cluster 模式提供高可用性

2. 应用场景

  • 计数器:可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量
  • 分布式ID生成:利用自增特性,一次请求一个大一点的步长如 incr 2000 ,缓存在本地使用,用完再请求
  • 海量数据统计:位图(bitmap):存储是否参过某次活动,是否已读谋篇文章,用户是否为会员, 日活统计
  • 会话缓存:可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性
  • 分布式队列/阻塞队列:List 是一个双向链表,可以通过 lpush/rpush 和 rpop/lpop 写入和读取消息。可以通过使用brpop/blpop 来实现阻塞队列
  • 分布式锁实现:在分布式场景下,无法使用基于进程的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁
  • 热点数据存储:最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据
  • 社交类需求:Set 可以实现交集,从而实现共同好友等功能,Set通过求差集,可以进行好友推荐,文章推荐
  • 排行榜:sorted_set可以实现有序性操作,从而实现排行榜等功能
  • 延迟队列:使用sorted_set,使用 【当前时间戳 + 需要延迟的时长】做score, 消息内容作为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数据做轮询处理。消费完再删除任务 rem key member

3.数据结构底层原理

3.1 String

redis 3.2 以前:

struct sdshdr {
    int len;
    int free;
    char buf[];
};

redis 3.2 后:

typedef char *sds;

struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
........
3.2 list

List是一个有序(按加入的时序排序)的数据结构,Redis采用quicklist(双端链表) 和 ziplist 作为List的底层实现

可以通过设置每个ziplist的最大容量,quicklist的数据压缩范围,提升数据存取效率

list-max-ziplist-size  -2        //  单个ziplist节点最大能存储  8kb  ,超过则进行分裂,将数据存储在新的ziplist节点中
list-compress-depth  1        //  0 代表所有节点,都不进行压缩,1, 代表从头节点往后走一个,尾节点往前走一个不用压缩,其他的全部压缩,2,3,4 ... 以此类推
3.3 Hash

Hash 数据结构底层实现为一个字典( dict ),也是RedisBb用来存储K-V的数据结构,当数据量比较小,或者单个元素比较小时,底层用ziplist存储,数据大小和元素数量阈值可以通过如下参数设置

hash-max-ziplist-entries  512    //  ziplist 元素个数超过 512 ,将改为hashtable编码 
hash-max-ziplist-value    64      //  单个元素大小超过 64 byte时,将改为hashtable编码
3.4 Set

Set 为无序的,自动去重的集合数据类型,Set 数据结构底层实现为一个value 为 null 的 字典( dict ),当数据可以用整形表示时,Set集合将被编码为intset数据结构。两个条件任意满足时,Set将用hashtable存储数据
1, 元素个数大于 set-max-intset-entries
2 , 元素无法用整形表示

set-max-intset-entries 512       // intset 能存储的最大元素个数,超过则用hashtable编码
3.5 ZSet

ZSet 为有序的,自动去重的集合数据类型,ZSet 数据结构底层实现为 字典(dict) + 跳表(skiplist) ,当数据比较少时,用ziplist编码结构存储

zset-max-ziplist-entries  128    // 元素个数超过128 ,将用skiplist编码
zset-max-ziplist-value     64     //  单个元素大小超过 64 byte, 将用 skiplist编码

4.Redis 6 特性

4.1 多线程

redis 6.0 提供了多线程的支持,redis 6 以前的版本,严格来说也是多线程,只不过执行用户命令的请求时单线程模型,还有一些线程用来执行后台任务, 比如 unlink 删除 大key,rdb持久化等

redis 6.0 提供了多线程的读写IO, 但是最终执行用户命令的线程依然是单线程的,这样,就没有多线程数据的竞争关系,依然很高效

redis 6.0 线程执行模式(配置):

io‐threads 4 // 这里说有三个IO线程,还有一个线程是main线程,main线程负责IO读写和命令执行操作

默认情况下,如上配置,有三个IO线程, 这三个IO线程只会执行 IO中的write 操作,也就是说, read 和 命令执行 都由main线程执行。最后多线程将数据写回到客户端。

开启配置:

io‐threads‐do‐reads yes // 将支持IO线程执行读写任务

在这里插入图片描述

4.2 client side caching 客户端缓存

redis 6 提供了服务端追踪key的变化,客户端缓存数据的特性,这需要客户端实现。
在这里插入图片描述

执行流程为, 当客户端访问某个key时,服务端将记录key 和 client ,客户端拿到数据后,进行 客户端缓存,这时,当key再次被访问时,key将被直接返回,避免了与redis 服务器的再次交 互,节省服务端资源,当数据被其他请求修改时,服务端将主动通知客户端失效的key,客户端 进行本地失效,下次请求时,重新获取最新数据。

4.3 ACL(对命令的访问和执行权限的控制,默认情况下,可以有执行任意的指令,兼容以前版本)

ACL设置方式:

  1. 命令方式: ACL SETUSER + 具体的权限规则, 通过 ACL SAVE 进行持久化
ACL SETUSER alice // 创建一个 用户名为alice的用户
  1. 对 ACL 配置文件进行编写,并且执行 ACL LOAD 进行加载

ACL存储有两种方式,但是两种方式不能同时配置,否则直接报错退出进程:

1.redis 配置文件: redis.conf
2.ACL配置文件, 在redis.conf 中通过 aclfile /path 配置acl文件的路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值