【中间件开发】Redis基础命令详解及概念介绍

文章目录

  • 前言
  • 一、Redis相关命令详解及原理
    • 1.1 string、set、zset、list、hash
      • 1.1.1 string
      • 1.1.2 list
      • 1.1.3 hash
      • 1.1.4 set
      • 1.1.5 zset
    • 1.2 分布式锁的实现
    • 1.3 lua脚本解决ACID原子性
    • 1.4 Redis事务的ACID性质分析
  • 二、Redis协议与异步方式
    • 2.1 Redis协议解析
      • 2.1.1 redis pipeline
      • 2.1.2 Redis协议图
    • 2.2 特殊协议操作-订阅发布
    • 2.3 异步redis协议
      • 2.3.1 hiredis + libevent
  • 总结


前言

本文介绍了Redis相关命令以及Redis当中的一些概念(协议)。


一、Redis相关命令详解及原理

内存是稀缺资源,所以:

  1. 当数据量少时,存储效率高为主
  2. 当数据量多时,运行速度快为主

1.1 string、set、zset、list、hash

  1. string 是一个安全的二进制字符串(兼容’\0’作为分隔符,安全指按长度);
  2. 双端队列 (链表) list :有序(插入有序);
  3. 散列表 hash:对顺序不关注,field 是唯一的;
  4. 无序集合 set:对顺序不关注,里面的值都是唯一的;
  5. 有序集合 zset :对顺序是关注的,里面的值是唯一的;根据 member 来确定唯一;根据 score 来 确定有序;

1.1.1 string

set key_test 1000get key_test# 原子减一
decr key_test
decrby key_test decrement(一个数字)# 原子加一
incr key_test
incrby key_test increment# set Not exist,当key_test存在时,什么也不做,否则等同于set
setnx key_test value
del key_test----------
# 
setbit key_test offset value
# 第offset位设置为value
getbit key_test offset
# 统计字符串被设置为1的bit数
bitcount key_test
----------

image.png

image.png
image.png

应用

  1. 对象存储:set,get
  2. 累加器:incr
  3. 分布式锁:setnx
  4. 位运算:setbit,getbit,bitcount

1.1.2 list

双向链表,首尾操作时间复杂度O(1);中间元素操作O(n)

  1. list.size < 48 不压缩
  2. 元素压缩前后长度差不超过8,不压缩

为什么压缩?如何压缩的?

# 从队列左侧入队
lpush key value ...
lpop key# 从队列右侧入队
rpush key value ...
rpop key # 尾索引
lrange key start end# 从存于 key 的列表里移除前 count 次出现的值为 value 的元素
lrem key count value# rpop的阻塞版本
brpop key timeout

image.png

应用

  1. 栈:lpush + lpop
  2. 队列:lpush + rpop
  3. 阻塞队列:lpush + brpop
  4. 异步消息队列
    1. 操作和队列一样,但是在不同系统间;生产者和消费者;
  5. 获取固定窗口记录
    1. ltrim key 0 4 保留最近5条记录

1.1.3 hash

散列表;C++ unordered_map

(节点数量 > 512 || 所有字符串长度 > 64) 采用dict
(节点数量 <= 512 || 所有字符串长度 < 64) 采用ziplist

hget key field
hgetallhset key field value
# 设置多个键值对
hmset key field1 value1 field2 value2 field3 value3 ... fieldn valuenhmget key field1 field2 ...hincrby key field increment
# 获取有多少个键值对
hlen keyhdel key field

image.png

应用

  1. 存储对象
  2. 购物车:商品列表用list,其中属性用hash

1.1.4 set

无序集合

(元素都为整数 && 节点数量 <= 512) 采用整数数组存储
(元素不全为整数 || 节点数量 > 512) 采用字典存储

# 添加一个或多个
sadd key member ...
# 计算集合元素个数
scard keysmembers key
# 返回成员member是否为key的成员
sismember key member
# 随机返回key集合中的一个或多个元素
srandmember key [count]
# 移除一个随机元素
spop key [count]
# 返回差集
sdiff key [key...]
# 返回交集
sinter key [key...]
# 返回并集
sunion key [key...]

image.png

应用

  1. 抽奖:srandmember
  2. 共同关注:sdiff ; sinter; sunion

1.1.5 zset

有序集合;实现排行榜;有序唯一


zadd key 
# 从key中删除member的键值对
zrem key member [member...]
# 返回有序集key中member的score值
zscore key member
# 成员member的score值加上增量
zincrby key increment member
# 返回个数
zcard key
# 返回排名
zrank key member
# 返回指定范围的元素
zrange key start stop
# 返回指定范围的元素(逆序)
zrevrange key start stop

image.png

应用

  1. 百度热榜
  2. 延时队列
  3. 分布式定时器
  4. 时间窗口限流

1.2 分布式锁的实现

释放锁操作:事务操作

锁:谁持有,谁释放

get dislock
-- 释放锁
local uuid = redis.call("get", KEYS[1])
if uuid == KEYS[2] thenredis.call("del", KEYS[1])
end

1.3 lua脚本解决ACID原子性

# 开启事务
multi# 提交事务
exec# 取消事务
discard# 检测key的变动
watch实际中是使用lua脚本
  • redis 中加载了一个 lua 虚拟机;用来执行 redis lua 脚本;
  • redis lua 脚本的执行是原子性的;
  • 当某个脚本正在执行的时候,不会有其他命令或者脚本被执行;
  • lua 脚本当中的命令会直接修改数据状态;
  • lua 脚本 mysql 存储区别:MySQL存储过程不具备事务性,所以也不具备原子性;

注意:如果项目中使用了 lua 脚本,不需要使用上面的事务命令
image.png

1.4 Redis事务的ACID性质分析

  • A 原子性;事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败;redis 不支持回滚;即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直 到将事务队列中的所有命令都执行完毕为止。

  • C 一致性;事务的前后,所有的数据都保持一个一致的状态,不能违反数据的一致性检测;这里 的一致性是指预期的一致性而不是异常后的一致性;所以 redis 也不满足;这个争议很大:redis 能 确保事务执行前后的数据的完整约束;但是并不满足业务功能上的一致性;比如转账功能,一个扣 钱一个加钱;可能出现扣钱执行错误,加钱执行正确,那么最终还是会加钱成功;系统凭空多了 钱;

set zhang 1000
lpush zhang 1 3 4 #error
get mark
  • I 隔离性;各个事务之间互相影响的程度;redis 是单线程执行,天然具备隔离性;

  • D 持久性;redis 只有在 aof 持久化策略的时候,并且需要在 appendfsync=always 才具备持久性;实际项目中几乎不会使用 redis.conf 中 aof 持久化策略;

  • 面试时候回答:lua 脚本满足原子性和隔离性;一致性和持久性不满足;

get zhang ==>100set zhang 200

如果这两个命令没有作为一个整体,那么可以会有另一条连接set。这将导致数据不一致。

什么时候探讨事务?多条并发连接
什么时候探讨原子操作?多核

二、Redis协议与异步方式

2.1 Redis协议解析

2.1.1 redis pipeline

redis pipeline 是一个客户端提供的机制,而不是服务端提供的;

注意:pipeline 不具备事务性;

目的:节约网络传输时间;

通过一次发送多次请求命令,从而减少网络传输的时间。

image.png

2.1.2 Redis协议图

image.png

上图描述了如何界定数据包:

  1. 长度 + 二进制流
  2. 二进制流 + 特殊分割符

2.2 特殊协议操作-订阅发布

为了支持消息的多播机制,redis引入了发布订阅:发送者发送消息,订阅者接收消息。

# 订阅频道
subscribe `channel`
# 订阅模式频道
psubscribe `channel`
# 取消订阅频道
unsubscribe `channel`
# 发布具体频道或模式频道的内容
publish `channel` `message`
# 客户端接收具体频道内容
message `specificChannel` `message`
# 客户端接收模式频道内容
pmessage

应用

  1. 发布订阅可以收到redis主动推送的内容
  2. 项目中支持发布订阅,需要另开一条连接

缺点

  1. 生产者传递来一条消息,redis找到相应的消费者并传递过去,如果没有消费者,消息丢弃;
  2. 如果有两个消费者,此时其中一个消费者挂掉了,重连上来将不会接收到该消息;
  3. redis停机重启,发布订阅的消息不会持久化。

2.3 异步redis协议

同步连接方案采用阻塞IO来实现
优点:代码书写是同步的,业务逻辑不割裂
缺点:阻塞当前线程,直到返回结果,通常需要多个线程来实现线程池来解决效率问题。

异步连接方案采用非阻塞IO来实现
优点:不阻塞当前线程,redis没有返回,可以继续向redis发送命令
缺点:代码书写是异步的,业务逻辑割裂,可以通过协程解决(skynet,openresty)

2.3.1 hiredis + libevent

我们需要做的事情:
适配

  1. 事件对象
  2. 事件操作函数

hiredis需要做:

  1. 协议解析
  2. 读写事件
  3. 缓冲区操作
  4. 协议加密等

适配事件对象和函数。

static int redisAttach(reactor_t *r, redisAsyncContext *ac) {redisContext *c = &(ac->c);redis_event_t *re;/* Nothing should be attached when something is already attached */if (ac->ev.data != NULL)return REDIS_ERR;/* Create container for ctx and r/w events */re = (redis_event_t*)hi_malloc(sizeof(*re));if (re == NULL)return REDIS_ERR;re->ctx = ac;re->e.fd = c->fd;re->e.r = r;// dont use event buffer, using hiredis's bufferre->e.in = NULL;re->e.out = NULL;re->mask = 0;ac->ev.addRead = redisAddRead;ac->ev.delRead = redisDelRead;ac->ev.addWrite = redisAddWrite;ac->ev.delWrite = redisDelWrite;ac->ev.cleanup = redisCleanup;ac->ev.data = re;return REDIS_OK;
}

总结

本文介绍了Redis的基本命令以及Redis协议中的部分内容。Redis是内存型数据库,围绕着内存的特性,Redis结合了lua脚本,分布式锁(最快的),异步连接等一系列特性。

参考链接:
https://github.com/0voice

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

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

相关文章

学习记录,正则表达式, 隐式转换

正则表达式 \\&#xff1a;表示正则表达式 W: 表示一个非字&#xff08;不是一个字&#xff0c;例如&#xff1a;空格&#xff0c;逗号&#xff0c;句号&#xff09; W: 多个非字 基本组成部分 1.字符字面量&#xff1a; 普通字符&#xff1a;在正则表达式中&#xff0c;大…

Selenium是广泛使用的模拟浏览器运行的库

简介 Selenium是广泛使用的模拟浏览器运行的库&#xff0c;它是一个用于Web应用程序测试的工具。 Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样&#xff0c;并且支持大多数现代 Web 浏览器。 环境 安装 pip install selenium下载Chrome驱动 系统环境…

网络练级宝典-> UDP传输层协议

目录 传输层 端口号 端口号和进程的关系 UDP协议 UDP协议格式 UDP数据封装&#xff1a; UDP数据分用&#xff1a; 面向数据报 UDP的缓冲区 UDP的缺点 基于UDP的应用层协议 传输层 端口号 我们知道端口号对应的其实就是一个进程的pid&#xff0c;在操作系统中二者的…

Redis原理—1.Redis数据结构

大纲 1.Redis的数据结构 2.Redis的SDS 3.Redis的链表 4.Redis的字典 5.Redis的跳跃表 6.Redis的整数集合 7.Redis的压缩列表 8.Redis的对象 9.Redis对象的几个关键属性 10.Redis的单线程为什么这么快 11.Redis的典型应用场景和说明 12.Redis的相关命令说明 1.Redis…

【Vue3中Router使用】

Vue3中Router使用 1. 安装vue-router组件2. 建两个测试页面2.1 测试页面Home.vue2.2 测试页面Category.vue 3. 创建路由对象4. 在入口main.js中引入router把App.vue改成路由页面5. 测试5.1 关闭检查解决ESlint报错5.2 改文件名解决ESlint检查报错测试WebHashHistory 和WebHisto…

python拆分Excel文件

按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文档样式如下&#xff1a; 结果&#xff1a;红色是按照Sheet名拆出的&#xff0c;蓝色和橙色是某个Sheet按照某列的不同值拆分的。 代码&#xff1a; # -*- coding: utf-8 -*- """ 拆分excel文件——按照…

交易所 Level-2 历史行情数据自动化导入攻略

用户部署完 DolphinDB 后&#xff0c;需要将历史股票数据批量导入数据库&#xff0c;再进行数据查询、计算和分析等操作。DolphinDB 开发了 ExchData 模块&#xff0c;主要用于沪深交易所 Level-2 行情原始数据的自动化导入&#xff0c;目前已支持的数据源包括&#xff1a; 沪…

开源ISP介绍(2)————嵌入式Vitis搭建

Vivado搭建参考前一节Vivado基于IP核的视频处理框架搭建&#xff1a; 开源ISP介绍&#xff08;1&#xff09;——开源ISP的Vivado框架搭建-CSDN博客 导出Hardware 在vivado中导出Hardware文件&#xff0c;成功综合—实现—生成比特流后导出硬件.xsa文件。&#xff08;注意导…

109.【C语言】数据结构之二叉树层序遍历

目录 1.知识回顾 2.代码实现 准备工作 LevelOrder函数 代码框架 关键代码 3.执行结果 1.知识回顾 层序遍历参见106.【C语言】数据结构之二叉树的三种递归遍历方式文章 截取的部分内容 定义:按层的方式遍历(,设n为树的深度,h1-->h2-->h3-->...-->hn) 以下面…

安装部署PowerDNS--实现内网DNS解析

PDNS是PowerDNS的缩写&#xff0c;是一个开源的DNS服务器软件。PowerDNS具有高性能、灵活性和可扩展性&#xff0c;可用于搭建各种规模的DNS解析服务。它支持多种后端数据库&#xff08;如MySQL、PostgreSQL等&#xff09;&#xff0c;提供高度定制化的配置选项&#xff0c;并具…

13.在 Vue 3 中使用OpenLayers加载鹰眼控件示例教程

在 WebGIS 开发中&#xff0c;鹰眼控件 是一个常用的功能&#xff0c;它可以为用户提供当前地图位置的概览&#xff0c;帮助更好地定位和导航。在本文中&#xff0c;我们将基于 Vue 3 的 Composition API 和 OpenLayers&#xff0c;创建一个简单的鹰眼控件示例。 效果预览 在最…

Elasticsearch 单节点安全配置与用户认证

Elasticsearch 单节点安全配置与用户认证 安全扫描时发现了一个高危漏洞&#xff1a;Elasticsearch 未授权访问 。在使用 Elasticsearch 构建搜索引擎或处理大规模数据时&#xff0c;需要启用基本的安全功能来防止未经授权的访问。本文将通过简单的配置步骤&#xff0c;为单节…

使用C#基于ADO.NET编写MySQL的程序

MySQL 是一个领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL 在网络上特别流行。MySQL 数据库可在大多数重要的操作系统平台上使用。它可在 BSD Unix、Linux、Windows 或 Mac OS 上运行。MySQL 有两个版本&#xff1a;MySQL 服务器系统和 MySQL 嵌入…

计算机视觉与各个学科融合:探索新方向

目录 引言计算机视觉与其他学科的结合 与医学的结合与机械工程的结合与土木工程的结合与艺术与人文的结合发文的好处博雅知航的辅导服务 引言 计算机视觉作为人工智能领域的重要分支&#xff0c;正迅速发展并渗透到多个学科。通过与其他领域的结合&#xff0c;计算机视觉不仅…

SpringBoot期末知识点大全

一、学什么 IoC AOP&#xff1a;面向切面编程。 事物处理 整合MyBatis Spring框架思想&#xff01; 二、核心概念 问题&#xff1a;类之间互相调用/实现&#xff0c;导致代码耦合度高。 解决&#xff1a;使用对象时&#xff0c;程序中不主动new对象&#xff0c;转换为由外部提…

QT模型/视图:自定义代理类型

简介 在模型/视图结构中&#xff0c;代理的作用就是在视图组件进入编辑状态编辑某个项时&#xff0c;提供一个临时的编辑器用于数据编辑&#xff0c;编辑完成后再把数据提交给数据模型。例如&#xff0c;在 QTableView 组件上双击一个单元格时&#xff0c;代理会提供一个临时的…

ubuntu中使用ffmpeg库进行api调用开发

一般情况下&#xff0c;熟悉了ffmpeg的命令行操作&#xff0c;把他当成一个工具来进行编解码啥的问题不大&#xff0c;不过如果要把功能集成进自己的软件中&#xff0c;还是要调用ffmpeg的api才行。 ffmpeg的源码和外带的模块有点太多了&#xff0c;直接用官网别人编译好的库就…

实现 DataGridView 下拉列表功能(C# WinForms)

本文介绍如何在 WinForms 中使用 DataGridViewComboBoxColumn 实现下拉列表功能&#xff0c;并通过事件响应来处理用户的选择。以下是实现步骤和示例代码。 1. 效果展示 该程序的主要功能是展示如何在 DataGridView 中插入下拉列表&#xff0c;并在选择某一项时触发事件。 2.…

Docker Compose实战一( 轻松部署 Nginx)

通过过前面的文章&#xff08;Docker Compose基础语法&#xff09;你已经掌握基本语法和常用指令认识到Docker Compose作为一款强大工具的重要性&#xff0c;它极大地简化了多容器Docker应用程序的部署与管理流程。本文将详细介绍如何使用 Docker Compose 部署 Nginx&#xff0…

【免费】如何考取HarmonyOS应用开发者基础认证和高级认证(详细教程)

HarmonyOS应用开发者认证考试PC网址 基础&#xff1a;华为开发者学堂 高级&#xff1a;华为开发者学堂 注&#xff1a;免费认证&#xff0c;其中基础认证有免费的课程&#xff0c;浏览器用Edge。 (新题库有点懒&#xff0c;不更新了&#xff0c;点赞收藏后找我要新题库 2024…