Redis简介和数据结构

目录

简介

进入之后身份认证才能使用

优点

用途:

数据结构

string

string自动扩容

Redis中的简单动态字符串(SDS)具有以下优点:

SDS数据的编码格式

比较:

string 常用操作

分布式锁

使用情况,保证接口幂等性 ?

分布式锁的应用???

list

常用操作

早期版本

压缩列表

优点

缺点

快速链表(quiklist)

set

set常用操作

set应用???

zset有序集合

存储结构

跳跃列表(skipList)

哈希散列表

存储结构


简介

Redis是一个开源的内存中数据结构存储系统,通常用作数据库、缓存和消息代理。它支持各种数据结构,包括字符串、哈希、列表、集合等,并提供了丰富的功能,如事务、持久化、发布/订阅等。

  1. 内存中数据结构存储系统:Redis主要将数据存储在内存中,这使得它具有非常高的读写速度。它通过使用持久化技术来保证数据在重启后不会丢失,因此即使是存储在内存中,也能够满足持久化的需求。

  2. 数据库、缓存和消息代理:Redis可以用作多种用途,包括传统数据库的替代品、缓存系统和消息代理。作为数据库,它可以存储各种类型的数据,并支持复杂的数据结构操作;作为缓存,它可以提供快速的数据访问,减轻后端数据库的压力;作为消息代理,它支持发布/订阅模式,可以用于实时通信和事件驱动架构。

  3. 支持多种数据结构:Redis支持多种数据结构,包括字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。这些数据结构能够满足不同场景下的数据存储和操作需求。

  4. 丰富的功能:除了基本的数据存储和检索功能外,Redis还提供了许多高级功能,如事务(Transaction)、持久化(Persistence)、发布/订阅(Pub/Sub)等。这些功能使得Redis在各种应用场景下都能发挥重要作用,并且具有很高的灵活性和扩展性。

总的来说,Redis是一个功能强大、性能优异的内存中数据存储系统,适用于各种场景下的数据管理和应用开发。

安装

sudo apt install redis-server

进入之后身份认证才能使用

redis-cli
auth 123456

优点

  1. 高性能: Redis是一个内存数据库,操作在内存中进行,因此具有快速的读写速度。

  2. 数据多样性: 支持不同类型的数据结构,如字符串、哈希、列表、集合、有序集合等,以及Bitmap和GEO地理信息等特殊数据类型。

  3. 持久化: 支持持久化数据到硬盘,可以根据需求选择RDB快照或者AOF日志文件的方式进行持久化。

  4. 发布/订阅模式: 支持消息代理模式,可以实现发布/订阅功能,方便实现消息通信。

  5. 分布式缓存: 支持主从复制和高可用性,可以搭建分布式缓存系统,提高系统的可靠性和容错性。

  6. 事务支持: 支持事务操作,可以将多个命令打包成一个原子操作进行执行,但不支持回滚。

  7. 功能丰富: 提供丰富的功能,如脚本执行(通过Lua脚本),可以实现复杂的业务逻辑。

用途:

  1. 排行榜: 使用有序集合(Sorted Set)数据类型,将每个成员的分数作为排名依据,可以通过自动排序功能实现排行榜功能。

  2. 限速器/计数器: 使用INCR命令对一个键进行自增操作,可以实现计数器功能。例如,可以将某个操作的频率限制在一定的速率内。

  3. 推送: 使用SET命令设置键值对,然后通过PUBLISH命令将消息推送给订阅者,实现简单的消息推送功能。

  4. 消息队列: 使用RPUSH命令向列表尾部添加消息,然后使用LPOP或者BLPOP命令从列表头部获取消息,可以实现基本的消息队列功能。LBPOP是一个阻塞命令,会在列表为空时等待直到有消息到来。

  5. 会话一致性: 可以使用Redis作为会话存储,将会话信息存储在Redis中,实现会话的统一管理和一致性。

MEMCATCH

数据结构

五种基础类型:

string

int类型的编码如果超过长度就会转化为string类型

SDS简单动态字符串:

基本结构结构体

struct sdshdr{
    //记录buf数组中已使用字符的数量,等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用的字符数量
     int free;
     //字符数组,用于保存字符串
    char buf[];
}
// 存储 “hello”
len:5
free:0
buf:['H','e','l','l','o','\0']

如上观察所得:

Redis 每次给 string 分配的空间都要大于字符串实际占用的空间,这样就在一定程度上提升了 Redis string 存储的效率,比如当字符串长度变大时,无需再重新申请内存空间。

string自动扩容

当字符串所占空间小于 1MB 时,Redis 对字符串存储空间的扩容是以成倍的方式增加的;而当所占空间超过 1MB 时,每次扩容只增加 1MB。Redis 字符串允许的最大值字节数是 512 MB。

Redis中的简单动态字符串(SDS)具有以下优点:

  1. 获取字符串长度的时间复杂度为O(1): SDS通过保存字符串的长度信息,使得获取字符串长度的操作时间复杂度为O(1),无论字符串长度多长,都能够在常数时间内完成。

  2. 安全的API: Redis的SDS API设计安全,函数使用是安全的,避免了由于字符串操作而引发的内存越界等问题。

  3. 保存二进制数据: SDS不仅可以保存文本数据,还可以保存二进制数据,因为SDS使用了类似C语言中的字符数组来存储数据,所以可以保存任意类型的数据,包括文本和二进制数据。

SDS数据的编码格式

在Redis中,简单动态字符串(SDS)可以存储文本数据,也可以存储二进制数据。在存储二进制数据时,Redis会使用 embstr(embedded string)或者 raw 编码来存储。

  • Embstr(嵌入式字符串): 当字符串长度较短(小于等于39字节,不同版本有所不同)时,Redis会选择使用 embstr 编码,将字符串直接存储在 SDS 结构体中,而不会进行额外的内存分配。这种方式节省了内存,提高了效率。

  • Raw 编码: 当字符串长度超过39字节时,Redis会使用 raw 编码,将字符串存储在单独的堆内存中,并在 SDS 结构体中保存指向堆内存的指针。这种方式适用于较长的字符串,可以避免嵌入式字符串带来的额外内存消耗。

比较:
  • embstr 编码创建字符串对象时,调用一次内存分配函数,raw调用两次

  • embstr 编码释放字符串对象时,调用一次内存释放函数,raw 调用两次

  • embstr 编码的字符串对象保存在一块连续的内存中,可以更好地利用 CPU 缓存提升性能

tips:

如果修改数据类型会怎样变换,会从embstr类型转为raw类型

string 常用操作

set设置字符串
get读取字符串
incr自增
decr自减
exists判断key是否存在
strlen返回字符串长度
del删除key
exprie设置过期时间
ttl查看剩余时间
sentnx不再存在就插入(成功返回(1))

分布式锁

在分布式系统中,当不同进程或线程一起访问共享资源时,会造成资源争抢,如果不加以控制的话,就会引发程序错乱。此时使用分布式锁能够非常有效的解决这个问题,它采用了一种互斥机制来防止线程或进程间相互干扰,从而保证了数据的一致性。

SETNX buy_lock value

setnxl buy 【接口名】 value 【time -》【过期时间】】

这样的命令来尝试获取名为 buy_lock 的锁。如果返回值是 1,表示成功获取了锁,可以执行后续的操作;如果返回值是 0,表示锁已经被其他客户端持有,需要等待或进行其他处理。

tip

设置过期时间:在设置分布式锁时,可以同时设置一个过期时间,以防止锁被持有的客户端出现异常或挂掉,导致锁无法正常释放而产生死锁问题。在 Redis 中,你可以使用 EXPIRE 命令来为锁设置一个过期时间,确保即使锁没有被主动释放,也能在一定时间后自动过期释放。

使用情况,保证接口幂等性 ?

Redis 分布式锁有很对应用场景,举个简单的例子,比如春运时,您需要在 12306 上抢购回家火车票,但 Redis 数据库中只剩一张票了,此时有多个用户来预订购买,那么这张票会被谁抢走呢?Redis 服务器又是如何处理这种情景的呢?在这个过程中就需要使用分布式锁。

分布式锁的应用???

分布式锁在各种场景下都有广泛的应用:

  1. 短链接服务:在短链接服务中,当多个用户同时请求生成短链接时,为了避免生成相同的短链接或者保证短链接的唯一性,可以使用分布式锁来确保同一时刻只有一个请求能够成功生成短链接。

  2. 会话存储:在分布式系统中,需要存储用户的会话信息,以实现用户登录状态的管理和跨服务的会话共享。使用分布式锁可以确保在写入或更新会话信息时的数据一致性和并发安全。

  3. 限流控制:在防止被恶意攻击或者保护服务稳定性的情况下,可以使用分布式锁来实现限流控制。例如,限制某个接口每秒的请求次数,通过分布式锁来控制并发请求的数量,避免服务被过载或者被恶意攻击。

list

常用操作

Redis中的列表(list)是一种支持双向操作的数据结构,类似于链表。它允许在列表的头部或尾部进行快速的添加和删除操作。这里是Redis列表的一些常用操作:

  1. 添加元素:

    • LPUSH key value [value ...]:向列表头部插入一个或多个元素。
    • RPUSH key value [value ...]:向列表尾部插入一个或多个元素。
  2. 删除元素:

    • LPOP key:从列表头部弹出一个元素。
    • RPOP key:从列表尾部弹出一个元素。
    • LREM key count value:从列表中删除指定数量的特定值。
  3. 获取元素:

    • LINDEX key index:根据索引获取列表中的元素,负数索引从列表尾部开始计数。
    • LRANGE key start stop:获取列表指定范围的元素。
  4. 设置元素:

    • LSET key index value:设置列表中指定索引处的值。
  5. 列表长度:

    • LLEN key:获取列表的长度。
  6. 删除列表:

    • LTRIM key start stop:保留列表指定范围内的元素,删除其他部分。

早期版本

如果列表元素个数小于512,采用压缩列表

列表每个元素的值都小于64字节

就会使用压缩列表ziplist

否则使用快速链表quicklist

压缩列表

  • 1、zlbytes:压缩列表的字节长度,占4个字节,因此压缩列表最长(2^32)-1字节;
  • 2、zltail:压缩列表尾元素相对于压缩列表起始地址的偏移量,占4个字节;
  • 3、zllen:压缩列表的元素数目,占两个字节;那么当压缩列表的元素数目超过(2^16)-1怎么处理呢?此时通过zllen字段无法获得压缩列表的元素数目,必须遍历整个压缩列表才能获取到元素数目;
  • 4、entryX:压缩列表存储的若干个元素,可以为字节数组或者整数;entry的编码结构后面详述;
  • 5、zlend:压缩列表的结尾,占一个字节,恒为0xFF

下面是entry每个元素的格式:

previous字段 为1Byte/5Byte

压缩列表(Compressed List)在存储和操作数据时具有一些优点,但同时也存在一些缺点。让我们更深入地探讨这些优点和缺点。

优点
  • 内存紧凑: 压缩列表通过减少冗余元数据和指针来节省内存空间。这种紧凑的结构特别适用于存储小型数据和少量元素。

  • 高效存储: 由于压缩列表以连续存储的方式组织数据,因此它在存储效率和内存占用上表现良好。

  • 灵活性: 压缩列表可以存储不同类型的数据,且不需要为每个元素额外分配内存空间,如链表中的指针或对象引用。

缺点
  • 不能保存过多元素: 压缩列表的结构在一定数量的元素下是高效的,但是当元素数量超出一定限度时,列表可能需要扩展和重组,导致性能下降。更大的数据集需要更多的内存和计算资源。

  • 不能保存过大的元素: 如果压缩列表中的某个元素非常大,可能会导致整个列表需要重新分配内存空间,称为连锁更新(Chain Update)。这是因为在压缩列表中,节点是连续存储的,改变一个节点可能影响整个列表的布局。

  • 不适合频繁修改: 由于压缩列表是紧凑存储的,插入和删除操作可能涉及重新排列整个列表,因此在频繁修改的场景下,效率可能低于其他数据结构,如链表。

  • 搜索和索引性能受限: 压缩列表的结构可能不适合复杂的搜索和索引操作。它通常适用于简单的遍历和查找,但不适用于需要高效索引的数据集。

快速链表(quiklist)

quicklist其实就是一个分段的ziplist,为什么这么说呢?其实quicklist存储数据基本单位是quicklistNode,每个quicklistNode的内容区就是以ziplist数据结构存储的。

 

set

Redis set (集合)遵循无序排列的规则,集合中的每一个成员(也就是元素,叫法不同而已)都是字符串类型,并且不可重复。Redis set 是通过哈希映射表实现的,所以它的添加、删除、查找操作的时间复杂度为 O(1)。集合中最多可容纳 2^32 - 1 个成员(40 多亿个)

set常用操作

  • sadd:添加新元素

  • smembers:列出集合中所有元素

  • sismember:判断元素是否在集合中

  • scard:返回集合中元素个数

  • srem:移除集合中一个或多个元素,如果移除的不存在就不处理

  • sinter:对两个集台求交集

  • sunion:对两个集合求并集

  • sdiff:对两个集合求差集

  • setnx:向 Redis 中添加一个 key,只用当 key 不存在的时候才添加并 返回1,存在则不添加返回 0

set应用???

在Redis中,Set是一种无序、不重复的数据集合,它的应用非常广泛。

  1. 集合运算:Redis提供了一系列的集合运算命令,如并集(Union)、交集(Intersection)、差集(Difference)等,可以对多个Set进行操作,得到新的集合结果。

  2. 标签(Tagging):可以将Set用于标签系统,每个元素代表一个标签,可以方便地对对象进行分类和检索。

  3. 好友关系:可以使用Set来表示用户的好友关系,每个用户的好友列表可以用一个Set来存储,方便进行好友相关操作,如查找共同好友、计算两个用户的共同好友数等。

  4. 唯一值存储:由于Set中的元素是唯一的,可以将Set用于存储唯一值,如网站的访问IP地址、用户的行为记录等。

  5. 实时统计:可以利用Set来进行实时统计,比如统计网站独立访客数、活跃用户数等。

  6. 过滤器:可以将Set用作过滤器,比如用于去重、检查某个元素是否存在等。

  7. 兴趣标记:可以将Set用于存储用户的兴趣标记,比如用户喜欢的电影、音乐等,方便进行个性化推荐。

zset有序集合

Redis zset(有序集合)中的成员是有序排列的,它和 set 集合的相同之处在于,集合中的每一个成员都是字符串类型,并且不允许重复;而它们最大区别是,有序集合是有序的,set 是无序的,这是因为有序集合中每个成员都会关联一个 double(双精度浮点数)类型的 score (分数值),Redis 正是通过 score 实现了对集合成员的排序。

存储结构

有序集合(zset)同样使用了两种不同的存储结构,分别是 zipList(压缩列表)和 skipList(跳跃列表),当 zset 满足以下条件时使用压缩列表:

  • 成员的数量小于128 个;
  • 每个 member (成员)的字符串长度都小于 64 个字节。

当 zset 使用压缩列表保存数据时,entry 的第一个节点保存 member,第二个节点保存 score。依次类推,集合中的所有成员最终会按照 score 从小到大排列。

当不满足使用压缩列表的情况时就使用跳跃列表

跳跃列表(skipList)
typedef struct zskiplistNode {
    // 后退指针
    struct zskiplistNode *backward;
    // 分值 权重
    double score;
    // 成员对象
    robj *obj;
    // 层
    struct zskiplistLevel {
        // 前进指针
        struct zskiplistNode *forward;
        // 跨度
        unsigned int span;
    } leval[];
} zskiplistNode;


typedef struct zskiplist {
    // 表头节点和表尾节点
    struct zskiplistNode *header, *tail;
    // 表中节点的数量
    unsigned long length;
    // 表中层数最大的节点的层数
    int leval;
} zskiplist;
  1. zskiplistNode 结构体:

    • backward:指向前一个节点的指针,用于向前遍历跳跃表。
    • score:节点的分值或权重,用于有序集合中排序节点。
    • obj:成员对象,实际存储在节点中的值。
    • leval:表示节点的层级信息的数组,包括前进指针和跨度(表示跨越的节点数量)。
  2. zskiplist 结构体:

    • header, tail:指向跳跃表头节点和尾节点的指针,用于快速访问跳跃表的起始和结束位置。
    • length:跳跃表中节点的数量,用于记录表的大小。
    • leval:表中层数最大的节点的层数,表示跳跃表的最大层级。

哈希散列表

Redis hash(哈希散列)是由字符类型的 field(字段)和 value 组成的哈希映射表结构(也称散列表),它非常类似于表格结构。在 hash 类型中,field 与 value 一一对应,且不允许重复。

存储结构

hash 类型是 Redis 常用数据类型之一,其底层存储结构有两种实现方式。

第一种,当存储的数据量较少的时,hash 采用 ziplist 作为底层存储结构,此时要求符合以下两个条件:

  • 哈希对象保存的所有键值对(键和值)的字符串长度总和小于 64 个字节。
  • 哈希对象保存的键值对数量要小于 512 个。

当无法满足上述条件时,hash 就会采用第二种方式来存储数据,也就是 dict(字典结构),该结构类似于 Java 的 HashMap,是一个无序的字典,并采用了数组和链表相结合的方式存储数据。在 Redis 中,dict 是基于哈希表算法实现的,因此其查找性能非常高效,其时间复杂度为 O(1)。

**哈希散列表也会有哈希冲突的现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/607053.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日Attention学习2——Multi-Scale Convolutional Attention

模块出处 [link] [code] [NIPS 22] SegNeXt: Rethinking Convolutional Attention Design for Semantic Segmentation 模块名称 Multi-Scale Convolutional Attention (MSCA) 模块作用 多尺度特征提取,更大感受野 模块结构 模块代码 import torch import torch.…

【启明智显技术分享】“ESP-IDF环境搭建全攻略:告别基于乐鑫方案彩屏开发中的搭建难题”

前言: 【启明智显】专注于HMI(人机交互)及AIoT(人工智能物联网)产品和解决方案的提供商,我们深知彩屏显示方案在现代物联网应用中的重要性。为此,我们一直致力于为客户提供彩屏显示方案相关的技…

深度解析:数据结构二叉树(1)

✅作者简介:大家好,我是再无B~U~G,一个想要与大家共同进步的男人😉😉 🍎个人主页: 再无B~U~G-CSDN博客 目标 1. 掌握树的基本概念 2. 掌握二叉…

分享10个高质量宝藏网站~

分享一波高质量宝藏网站~ 这10个宝藏网站,个个都好用到爆,娱乐、办公、学习都能在这里找到! 1、Z-Library https://zh.zlibrary-be.se/ 世界最大的免费电子书下载网站!电子书资源超千万,不过这个网站不太稳定&#…

网络原理

UDP 特点:无连接 不可靠传输 面向数据报 全双工 报文格式: UDP数据报UDP报头UDP载荷(应用层数据报) | 源端口 目的端口 报文长度 校验和 TCP 特点:有连接 可靠传输 面向字节流 全双工 作为传输层…

C++实验五 : 类的继承 -----CUST

【题目】 1.定义person类,包括数据私有成员:姓名,性别;共用成员函数:带参数构造函数,display函数输出本类对象的所有数据成员值。 2.定义student类,保护继承person类;增加保护数据成…

怎么找投资白银的贵金属交易平台?

在当今的投资市场中,白银作为一种贵金属,一直受到投资者的广泛关注。但是,如何选择一家可靠的贵金属交易平台进行投资呢?这是许多投资者面临的难题。本文将从多个角度为投资者详细解析如何找到一家值得信赖的贵金属交易平台。 我们…

多模态大模型通过外接数据方案实现电力智能巡检(设计方案)

大模型相关目录 大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步,扬帆起航。 大模型应用向开发路径:AI代理工作流大模型应用开发实用开源项目汇总大模…

TSINGSEE青犀视频边缘计算AI智能分析网关V4告警消息语音推送的配置流程

TSINGSEE青犀视频边缘计算硬件智能分析网关V4内置了近40种AI算法模型,支持对接入的视频图像进行人、车、物、行为等实时检测分析,上报识别结果,并能进行语音告警播放。今天我们来分享一下如何配置和使用AI智能分析网关V4的语音推送。 提前准备…

webrtc初步了解

WebRTC搭建点对点实时音视频对话,起始需要保证完成两点: 1.媒体协商,了解彼此支持的媒体格式。参与视频通讯的双方必须先交换SDP信息,交换SDP的过程。 2.网络协商,了解彼此的网络环境,找到一条相互通讯的链…

【SpringBoot整合系列】SpringBoot整合RabbitMQ-消息可靠性

目录 确保消息的可靠性RabbitMQ 消息发送可靠性分析解决方案开启事务机制发送方确认机制单条消息处理消息批量处理 失败重试自带重试机制业务重试 RabbitMQ 消息消费可靠性如何保证消息在队列RabbitMQ 的消息消费,整体上来说有两种不同的思路:确保消费成…

基于Java+SpringBoot+Vue+echarts健身房管理系统设计和实现

基于JavaSpringBootVueecharts健身房管理系统设计和实现 🍅 作者主页 网顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系…

Axure PR 10 下拉三级菜单设计图

在线预览地址:Untitled Document 程序员必备资源网站:天梦星服务平台 (tmxkj.top) 需要源码设计图联系我wx:19948765606,3块钱拿走

k8s 使用Docker和Containerd对比分析

目录 k8s 使用Docker和Containerd对比分析 互动1:docker build构建的镜像和containerd镜像通用吗? 互动2:k8s1.24之前版本和1.24及1.24之后版本区别? k8s 使用Docker和Containerd对比分析 如果你使用Docker作为K8S容器运行时的…

orbslam2基础

目录 一、 内容概要二、 orbslam2基础介绍三 、 orbslam2安装3.1 安装依赖3.2 安装orbslam23.3 下载Kitee数据集 四、 进行ORBSLAM2仿真五、 心得体会六、 参考链接 一、 内容概要 orbslam2基础介绍orbslam2安装orbslam2使用案例:orbslam2kitti数据集序列图像 二、…

python3安装教程

1.下载python 百度网盘下载python-3.12.3-amd64.exe 链接:https://pan.baidu.com/s/1MV3kvVdjCdS_G-_KgefwLw?pwdpgzu 提取码:pgzu 官网下载:Welcome to Python.org 有很多版本,选择需要的版本下载 2.安装python 双击python-…

作为餐饮行业HR,怎么选择一套合适的HCM人事管理系统?

在餐饮业这个行业中,人员流动性较高,特别是对于服务员和厨师这类基层员工,招聘一直是一个难题。根据艾瑞数据测算,到2024年,中国餐饮行业的年收入将超过6万亿元,年复合增长率高达8.8%。作为餐饮企业的品牌战…

RV32I指令集及其编码方式解读

文章目录 前言RISCV指令集的模块化RV32IR型指令I型指令load指令 (I型) S型指令B型指令 (S型指令变体)PC相对地址B型指令简单举例 U型指令LUI指令li伪指令 AUIPC指令 J型指令(U型指令变体)JAL指令JALR指令(I型指令) 注参考 前言 R I S C − V RISC-V RISC−V 表示精简指令集计算…

汽车IVI中控开发入门及进阶(十七):IVI的功耗管理

汽车人机界面(HMI)系统旨在使驾驶员能够在不分心的情况下与车辆互动。HMI可以通过触摸板、按钮或语音系统在人和机器之间建立更自然的互动。对连接解决方案、低成本HMI软件和增强的用户体验(UX)的需求不断增加,使得平视显示器(HUD)、后座娱乐系统、基于转向的控制、仪表…

第42天:WEB攻防-PHP应用MYSQL架构SQL注入跨库查询文件读写权限操作

第四十二天 一、PHP-MYSQL-SQL注入-常规查询 1.PHP-MYSQL-Web组成架构 MySQL(统一管理) ​ root(自带默认) ​ 网站A testA ​ 网站B testB MySQL(一对一管理) ​ testA用户 ​ 网站A testA ​ testB用户 ​ 网站B testB access无数据库用户 m…