【Redis -String、List介绍和应用场景】

news2024/11/24 4:32:12

String

  • String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串, 也可以是数字(整数或浮点数),value 最多可以容纳的数据长度是 512M。

内部实现

  • String 类型的底层的数据结构实现主要是 int 和 SDS(简单动态字符串)。

    • SDS 不仅可以保存文本数据,还可以保存二进制数据。(SDS的所有API都会以处理二进制的方式来处理 SDS 存放在 buf[] 数组里的数据)
    • SDS 获取字符串长度的时间复杂度是 O(1)。(len 属性记录了字符串长度)
    • Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。(SDS 在拼接字符串之前会检查 SDS 空间是否满足要求)
  • 字符串对象的内部编码(encoding)有 3 种 :int、raw和 embstr。
    在这里插入图片描述

    • 字符串对象保存的是整数值,并且这个整数值可以用long类型来表示,那么字符串对象会将整数值保存在字符串对象结构的ptr属性里面(将void*转换成 long),并将字符串对象的编码设置为int
      在这里插入图片描述
    • 字符串对象保存的是一个字符串,并且这个字符申的长度小于等于 32 字节,字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串,并将对象的编码设置为embstr
      在这里插入图片描述
    • 字符串对象保存的是一个字符串,并且这个字符串的长度大于 32 字节(redis 2.+版本),那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串,并将对象的编码设置为raw
      在这里插入图片描述
  • embstrraw的区别

    • embstr会通过一次内存分配函数来分配一块连续的内存空间来保存redisObject和SDS,而raw编码会通过调用两次内存分配函数来分别分配两块空间来保存redisObject和SDS
  • embstr优点

    • embstr编码将创建字符串对象所需的内存分配次数从 raw 编码的两次降低为一次;
    • 释放 embstr编码的字符串对象同样只需要调用一次内存释放函数;
    • embstr编码的字符串对象的所有数据都保存在一块连续的内存里面可以更好的利用 CPU 缓存提升性能。
  • embstr缺点

    • 如果字符串的长度增加需要重新分配内存时,整个redisObject和sds都需要重新分配空间,所以embstr编码的字符串对象实际上是只读的,当我们对embstr编码的字符串对象执行任何修改命令(例如append)时,程序会先将对象的编码从embstr转换成raw,然后再执行修改命令。

应用场景

缓存对象

  • 使用 String 来缓存对象有两种方式:
    • 直接缓存整个对象的 JSON(SET user:1 '{"name":"xiaolin", "age":18}')
    • 采用将 key 进行分离为 user:ID:属性,采用 MSET 存储,用 MGET 获取各属性值(MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20。)

常规计数

  • 因为 Redis 处理命令是单线程,所以执行命令的过程是原子的。因此 String 数据类型适合计数场景,比如计算访问次数、点赞、转发、库存数量等等。
# 初始化文章的阅读量
> SET aritcle:readcount:1001 0
OK
#阅读量+1
> INCR aritcle:readcount:1001
(integer) 1
> GET aritcle:readcount:1001
"1"

分布式锁

  • SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁:
    • 如果 key 不存在,则显示插入成功,可以用来表示加锁成功;
    • 如果 key 存在,则会显示插入失败,可以用来表示加锁失败。

分布式锁加上过期时间

SET lock_key unique_value NX PX 10000

共享 Session 信息

  • 借助 Redis 对这些 Session 信息进行统一的存储和管理,这样无论请求发送到那台服务器,服务器都会去同一个 Redis 获取相关的 Session 信息,这样就解决了分布式系统下 Session 存储的问题。

在这里插入图片描述

List

  • List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。

内部实现

  • List 类型的底层数据结构是由双向链表或压缩列表实现的:
    • 如果列表的元素个数小于 512 个,列表每个元素的值都小于 64 字节。Redis 会使用压缩列表作为 List 类型的底层数据结构;
    • 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构;

在 Redis 3.2 版本之后 List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表。

应用场景

消息队列

  • 消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性。

1.消息保存
在这里插入图片描述
List 可以使用LPUSH + RPOP(或者反过来,RPUSH+LPOP)命令实现消息队列。

  • 生产者使用 LPUSH key value[value…] 将消息插入到队列的头部,如果 key 不存在则会创建一个空的队列再插入消息。
  • 消费者使用 RPOP key 依次读取队列的消息,先进先出。

缺点

  • 当有消息送达时,List不会主动通知消费者有消息写入,消费者只能while(1)循环不断检查,有消息则返回结果,无消息返回空继续循环。

解决办法

  • BRPOP命令也称为阻塞式读取,客户端在没有读到队列数据时,自动阻塞,直到有新的数据写入队列,再开始读取新数据
    在这里插入图片描述

2.处理重复消息

  • 每个消息都有一个全局的 ID。
  • 消费者要记录已经处理过的消息的 ID。(将已处理的ID和要处理的ID对比)

但是 List 并不会为每个消息生成 ID 号,所以我们需要自行为每个消息生成一个全局唯一ID,生成之后,我们在用 LPUSH 命令把消息插入 List 时,需要在消息中包含这个全局唯一 ID。

> LPUSH mq "111000102:stock:99"
(integer) 1

3.保证消息可靠性

消费者程序在处理消息的过程出现了故障或宕机,就会导致消息没有处理完成,那么,消费者程序再次启动后,就没法再次从 List 中读取消息了。

  • List 类型提供了 BRPOPLPUSH 命令,这个命令的作用是让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存。

4.List做消息队列缺陷

  • List 不支持多个消费者消费同一条消息,因为一旦消费者拉取一条消息后,这条消息就从 List 中删除了,无法被其它消费者再次消费。
  • 要实现一条消息可以被多个消费者消费,那么就要将多个消费者组成一个消费组,但是 List 类型并不支持消费组的实现。而新类型Stream支持消费组形式的消息读取。

原文来自https://www.xiaolincoding.com/redis/data_struct/command.html#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF-2

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

万字解析,带你深入掌握多种排序算法!-C语言

今天我们来看排序,排序在生活中经常使用,非常重要,是必学的内容。 目录 1.插入排序 1.1直接插入排序 1.2希尔排序 2.选择排序 2.1直接选择排序 2.2堆排序 3.交换排序 3.1冒泡排序 3.2快速排序 3.2.1挖坑法 3.2.2左右指针法 3.2.3…

【驯服野生verilog-mode全记录】day4 —— 对循环展开语法的python脚本外挂支持

我们的目标是┏ (゜ω゜)☞芯片前端全栈工程师~喵! 系列文章目录 【驯服野生verilog-mode全记录】day3 —— 基于vim自动生成verilog-mode格式初始文件模板_尼德兰的喵的博客-CSDN博客 【驯服野生verilog-mode全记录】day2 —— 模块的例化_尼德兰的喵的博客-CSDN…

微服务框架 SpringCloud微服务架构 服务异步通讯 53 MQ 集群 53.4 仲裁队列【RabbitMQ控制台搭建】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 服务异步通讯 文章目录微服务框架服务异步通讯53 MQ 集群53.4 仲裁队列【RabbitMQ控制台搭建】53.4.1 仲裁队列53.4.2 搭建仲裁队列53 MQ 集…

10. 注解开发Bean作用范围和生命周期管理

1. bean作用范围注解配置 使用Scope注解定义bean作用范围 1.1. singleton为单例 1.1.1 在bean头上使用Scope注解,singleton package com.lin.dao.impl;import com.lin.dao.BookDao; import org.springframework.context.annotation.Scope; import org.springfra…

企业档案管理实务:档案的检索方法知多少

在鸿翼档案的企业档案系统设计中,企业档案常用的检索实际上包括两个行为:企业档案信息的贮存和企业档案信息的查找。档案检索工具一方面是整个企业档案检索体系中贮存结果的最终体现,直接反映贮存的质量和水平;另一方面又是各项业…

Redis 哈希(Hash)方法使用详解

目录一、简介二、常用方法2.1、HSET2.2、HSETNX2.3、HGET2.4、HINCRBY、HINCRBYFLOAT2.5、HSTRLEN2.6、HEXISTS2.7、HDEL2.8、HLEN2.9、HMSET、HMGET2.10、HKEYS、HVALS、HGETALL2.11、HSCAN一、简介 本文今天主要是讲哈希(Hash)的方法的使用&#xff0c…

毕业设计 单片机手势检测识别系统 - arduino 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理5 部分核心代码6 最后0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长…

uniapp中video层级太高(或者在页面中不跟随页面滚动)解决方案

我觉得这个问题有必要记录一下。最近项目中遇到的问题:项目是uniapp开发,有一个商品详情的页面和一个视频竖向轮播的页面。 问题描述 1、商品详情页上面是图片轮播(包含视频),下面是商品详情,当页面上下滑动时,如果当…

微服务框架 SpringCloud微服务架构 服务异步通讯 52 惰性队列 52.2 惰性队列

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 服务异步通讯 文章目录微服务框架服务异步通讯52 惰性队列52.2 惰性队列52.2.1 惰性队列52.2.2 总结52 惰性队列 52.2 惰性队列 52.2.1 惰…

【BTC】Fork

区块链中fork的分类: state fork: 两个节点差不多同一个时候挖到了矿,就会出现一个临时性的分叉。 forking attack(deliberate fork):也是属于对比特币这个区块链当前的状态产生的意见分歧,只不…

汇编语言笔记——汇编程序开发、汇编大作业

文章目录传送门汇编程序开发汇编代码初步实践dos虚拟机与挂载实模式Hello World代码解析汇编链接重新汇编与批处理反汇编与debug保护模式Hello WorldVS2017masm32环境配置汇编基础语言概述汇编环境汇编语言语句格式常用伪指令数据定义符号定义操作符\$OFFSET算术操作符逻辑操作…

【基础】RabbitMQ 基础

RabbitMQ 基础RabbitMQ 基本介绍RabbitMQ 基本概念ConnectionChannelVirtual HostQueueExchangedirectfanouttopicheadersRabbitMQ 基本介绍 RabbitMQ 是使用 Erlang 语言开发的基于 AMQP 协议来实现的开源消息队列系统。 RabbitMQ 的特点: 灵活路由:E…

社招前端二面react面试题整理

解释 React 中 render() 的目的。 每个React组件强制要求必须有一个 render()。它返回一个 React 元素&#xff0c;是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素&#xff0c;则必须将它们组合在一个封闭标记内&#xff0c;例如 <form>、<group>、<div&g…

什么是数据标注,它的用途是什么?

什么是数据标注&#xff1f; 从本质上讲&#xff0c;数据标注是对计算机视觉或自然语言处理 (NLP)可识别的材料内容进行标记的过程。当我们标记或标注这些类型的数据时&#xff0c;它们变得更容易输入算法或编程以通过 NLP 进行解释。 得益于数据标注&#xff0c;人工智能 (…

【Vue】Vue项目打包上线流程--20221219

Vue项目打包上线流程 我的链接https://blog.csdn.net/m0_46629123/article/details/128371149 1.打包 npm run build 2.准备服务器 1.准备demo文件夹&#xff0c;并CMD输入npm init 2.CMD输入npm i express 3.新建并编辑server.js server.js const express require(…

电动汽车对系统运行的影响(Matlab实现)

目录 0 写在前面 1 插式电动车介绍 2 全系统 PEV 充电需求估算 2.1 旅行模式模型 2.2 能源消耗模型 2.3 电力消耗模型 3 单个 PEV 充电设施需求估算 4 PEV充电站需求估算网络 5 电动汽车对电力系统影响的评估 6 系统模型 6.1 结果 6.2 Matlab代码 0 写在前面 在不久…

论文笔记High-Resolution Image Synthesis with Latent Diffusion Models

普通的扩散模型在像素空间操作&#xff0c;运算复杂度较高。为了保证在低资源下训练扩散模型&#xff0c;并保留扩散模型的质量和灵活性&#xff0c;该论文使用预训练的自编码器得到隐含空间&#xff0c;并在隐含空间中训练扩散模型。另一方面&#xff0c;该论文使用cross-atte…

设计模式原则 - 里氏替换原则

一 背景&#xff1a; 里氏替换原则是针对继承的。介绍前先聊聊继承性的特点 继承优势 提高代码的复用性&#xff08;每个子类有拥有父类的属性和方法&#xff09;提高代码的可扩展性 继承劣势 继承是侵入性的&#xff08;只要继承&#xff0c;就必须拥有父类的属性和方法&…