Redis 协议与异步方式

news2024/10/6 6:52:34

redis pipeline 模式

  • redis pipeline 是一个客户端提供的机制,与 redis 无关。
  • pipeline 不具备事务性。
  • 目的:节约网络传输时间。
  • 通过一次发送多条请求命令,从而减少网络传输时间。
    在这里插入图片描述
  • 时间窗口限流
    • 系统限定某个用户某个行为在指定的时间范围内(动态)只能发生 N 次
# 指定用户 user_id 的某个行为 action 在特定时间内 period 只允许发生该行为的最大次数 max_count
# 维护一次时间窗口,将窗口外的记录全部清理掉,只保留窗口内的记录
local function is_action_allowed(red, userid, action, period, max_count)
    local key = tab_concat({"hist", userid, action}, ":")
    local now = zv.time()
    red:init_pipeline()
    -- 记录行为
    red:zadd(key, now, now)
    -- 移除时间窗口之前的行为记录,剩下的都是时间窗口内的记录
    red:zremrangebyscore(key, 0, now - period * 100)
    -- 获取时间窗口内的行为数量
    red:zcard(key)
    -- 设置过期时间,避免冷用户持续占用内存 时间窗口的长度 + 1秒
    red:expire(key, period + 1)
    local res = red:commit_pipeline()
    return res[3] <= max_count
end

redis 发布订阅模式

  • 为了支持消息的多播机制,redis 引入了发布订阅模块。
  • 作用:
    • 没有建立连接的服务器之间进行交互。
    • 第三方系统和与 redis 建立连接的服务器之间进行交互。
  • 缺点:不确定消息到达。kafka 分布式消息队列、redis stream 模式可以确保消息到达。
    • 发布订阅的生产者传递过来一个消息,redis 会直接找到相应的消费者并传递过去。假如没有消费者,消息直接丢弃。假如开始有 2 个消费者,一个消费者突然挂掉了,另一个消费者依然能接收到消息。但是,如果刚挂掉的消费者重新连上后,在断开连接期间的消息对于该消费者来说彻底丢失了。
    • redis 停机重启,pubsub 的消息是不会持久化的,所有的消息都被直接丢弃。
  • 使用场景
    • 业务可以接受消息丢失。
    • redis cluster 集群之间通信。
  • 服务器需要和 redis 建立多少连接
    • 5 种基本数据结构的处理,只需要一条连接,可以使用连接池。
    • 如果有阻塞连接的需求,另外建立一条连接。
    • 如果需要发布订阅模式,另外建立一条连接。

在这里插入图片描述

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

subscribe news.A news.B news.C
psubscribe news.*
publish new.B 'zcoder is good'

redis 事务

  • 前提:有并发连接。
  • 事务是用户定义的一系列的数据库操作,要么全部执行,要么全部不执行,是不可分割的单元。
  • redis 事务原理:当使用 MULTI 开启事务时,redis 会创建一个队列,后续的所有命令都会入队,直到使用 EXEC 提交事务。提交事务时会将队列中的所有命令出队执行。因为 redis 处理命令是单线程的,所以在处理队列中的命令时会阻塞其它连接的命令,直到队列中的命令全部处理完。使用 DISCARD 可以清空队列。使用 WATCH 可以观察 key,如果 key 对应的 value 变动,说明其它连接修改了 value,事务的逻辑一致性被破坏,那么调用 EXEC 就会清空该事务的队列,返回 nil。
# 开启事务
MUITI
# 提交事务 
EXEC
# 取消事务
DISCARD

# 检测 key 对应的 value 的变动,若在事务执行中,value 变动则取消事务并返回 nil。
# 在事务开启前调用,乐观锁实现(cas) 
WATCH
  • 应用
    • 加倍操作
      WATCH score
      val = GET score
      MULTI
      SET score val * 2
      EXEC
      

lua 脚本

  • redis 中加载了一个 lua 虚拟机,用来执行 lua 脚本。
  • redis lua 脚本的执行是原子性的,当某个脚本正在执行的时候,不会有其他命令或者脚本被执行。
  • lua 脚本中的命令会直接修改数据状态。
  • 先将 lua 脚本提交到 redis 中,redis 会通过 lua 虚拟机解析 lua 脚本,并返回一个 hash 值,这个 hash 值可以代替这个 lua 脚本(通过这个 hash 值去索引对应的 lua 脚本)。
    • 优点:使用较短的字符串代替复杂的 lua 脚本。意味着在网络传输的过程中可以减少发送数据的流量。其次,效率会更高,因为使用的是已经编译好的 lua 脚本。
      在这里插入图片描述
# 测试使用
EVAL script numkeys key [key ...] arg [arg ...]

# 线上使用
EVALSHA sha1 numkeys key [key ...] arg [arg ...]
  • 应用
    • 项目启动时,建立 redis 连接并验证,通过 script load 加载项目中使用的 lua 脚本,script load 会返回对应 lua 脚本的 hash 值。
    • 项目中若需要热更新,通过 redis-cli 执行 script flush 然后可以使用订阅发布功能通知所有服务器重新加载 lua 脚本。
    • 若项目中 lua 脚本发生阻塞,可通过 script kill 暂停当前阻塞脚本的执行。
# 从文件中读取 lua脚本内容
cat test.lua | redis-cli script load --pipe
# 加载 lua脚本字符串 生成 sha1
> script load 'local val = KEYS[1]; return val'
"b8059ba43af6ffe8bed3db65bac35d452f8115d8"
# 检查脚本缓存中,是否有该 sha1 散列值的lua脚本
> script exists "b8059ba43af6ffe8bed3db65bac35d452f8115d8"
1) (integer) 1
# 清除所有脚本缓存
> script flush
OK
# 如果当前脚本运行时间过长(死循环),可以通过 script kill杀死当前运行的脚本
> script kill
(error) NOTBUSY No scripts in execution right now.

ACID 特性

  • 原子性(A)
    • 事务是一个不可分割的单位,事务中的操作要么全部成功,要么全部失败。
    • redis 不支持回滚,即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。
  • 一致性(C)
    • 事务的前后,所有的数据都保持一个一致的状态,不能违反数据的一致性检测。这里的一致性是指预期的一致性而不是异常后的一致性,所以 redis 也不满足。
      • 这个争议很大:redis 能确保事务执行前后的数据的完整约束,但是并不满足业务功能上的一致性,比如转账功能,一个扣钱一个加钱,可能出现扣钱执行错误,加钱执行正确,那么最终还是会加钱成功,系统凭空多了钱。
  • 隔离性(I)
    • 各个事务之间互相影响的程度,redis 是单线程执行,天然具备隔离性。
  • 持久性(D)
    • redis 只有在 aof 持久化策略的时候,并且需要在 redis.conf 中 appendfsync=always 才具备持久性,实际项目中几乎不会使用 aof 持久化策略。
  • lua 脚本满足原子性和隔离性,不满足一致性和持久性

redis 异步连接

  • 同步连接方案采用阻塞 io 实现。通常用多个线程实现线程池解决效率问题。
    • 优点:代码书写是同步的,业务逻辑没有割裂。
    • 缺点:阻塞当前线程,直至 redis 返回结果。
  • 异步连接方案采用非阻塞 io 实现。
    • 优点:没有阻塞当前线程,就算 redis 没有返回,依然可以往 redis 发送命令。
    • 缺点:代码书写是异步的(回调函数),业务逻辑割裂。
  • 基于 reactor 实现异步连接:
    1. 与 redis 建立连接
    a. 创建 socket, 设置 fd 为非阻塞 io
    b. 调用 connect(fd, &addr, &len)
    c. 将 fd 注册到 epoll, 注册写事件
    d. 如果连接建立成功, fd 的写事件会进行响应, 然后注销写事件
    
    1. 向 redis 发送数据(使用 redis 协议加密,然后通过 tcp 发送过去)
    a. int n = write(fd, buf, sz)
       如果 n < sz && n != -1 或者 n == -1 && errno = EWOULDBLOCK 
       说明 fd 对应的发送缓冲区已经满了
    b. 注册写事件, 如果写事件触发, 继续 write(fd, buf, sz),
       如果发送完毕, 注销写事件
    c. 注册读事件
    
    1. 读取 redis 的返回(通过 tcp 接收数据并分割数据包,然后使用 redis 协议解密)
    a. 读事件触发, int n = read(fd, buf, sz)
    b. 根据 redis 协议分割数据包
    c. 使用 redis 协议解密
    

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

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

相关文章

华为HCIP Datacom H12-821 卷2

1.单选题 下面关于 OSPF 中的 ABR&#xff0c;描述措误的是 A、ABR 不能够产生三类、四类、五类 LSA B、将连接的非骨干区域内的一类、二类 LSA 转换成三类 LSA,发布到骨干区域中 C、ABR 格骨干区城内的一类、二类 LSA.三类 LSA 转换成三类 LSA, 发布到连接的非骨干区域中 …

【系统分析师】-软件工程

1、信息系统的生命周期 1、四阶段划分 立项阶段&#xff1a;企业全局、形成概念、需求分析。包含【系统分析师】-系统规划-CSDN博客开发阶段&#xff1a;总体规划--系统分析--设计--实施--验收运维阶段&#xff1a;通过验收、移交之后消亡阶段&#xff1a;更新改造、功能扩展…

【Excel PDF 系列】iText 库直接实现表格 PDF

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录 前言生成表格 PDF 效果引入 pom 配置代码实现定义 CreateExcelToPdfModel 对象主方法 前言 最近遇到生成 E…

web学习笔记(二十一)

目录 1.构造函数创建对象 1.1规则 1.2 new关键字调用构造函数时&#xff0c;函数内部做了什么事情&#xff1f; 1.3总结 2.混合模式创建对象 3.JavaScript 继承---借助构造函数 4.原型链 4.1原型链实现方法继承 5.完美的组合继承 6.call方法的使用 1.构造函数创建对象…

1、docker入门

文章目录 1、tocker简介2、tocker的安装&环境配置2、配置阿里云镜像3、基本命令1、镜像命令2、docker基本命令3、镜像基本命令4、Docker 容器常用命令 1、tocker简介 新一代的虚拟化技术 2、tocker的安装&环境配置 uname -r1、首先查看liunx的内核 yum update -y2、更…

Nginx----高性能的WEB服务端(四)

一、http 协议反向代理 1、反向代理&#xff1a;缓存功能 ​ proxy_cache zone_name | off; 默认off #指明调用的缓存&#xff0c;或关闭缓存机制;Context:http, server, location #zone_name 表示缓存的名称.需要由proxy_cache_path事先定义proxy_cache_key string; #缓存中…

刚刚:阿里云服务器降价了!2024云服务器优惠价格表曝光!

2024阿里云服务器优惠活动政策整理&#xff0c;轻量2核2G3M服务器61元一年、2核4G4M带宽165元1年&#xff0c;云服务器4核16G10M带宽26元1个月、149元半年&#xff0c;阿里云ECS云服务器2核2G3M新老用户均可99元一年续费不涨价&#xff0c;企业用户2核4G5M带宽199元一年&#x…

如何开展有效的绩效面谈

绩效面谈作为绩效管理的核心环节&#xff0c;其重要性不容忽视。它不仅是评价员工过去一段时间工作表现的环节&#xff0c;更是为下一阶段绩效管理设定目标和方向的环节。然而&#xff0c;许多企业在实施绩效面谈时&#xff0c;往往仅停留在形式上&#xff0c;没有真正地发挥其…

16. QML中的一些粒子特效

1.说明 在使用unity开发游戏时&#xff0c;都会涉及到一些特效的开发。实际上在QML中也提供了一些可以做特效的控件&#xff0c;称之为粒子系统。本篇博客主要记录一些使用粒子做特效的方式。 特效–火焰效果&#xff1a; 2. 案例汇总 2.1 案例1 效果展示&#xff1a; 粒子…

仿牛客网项目---用户注册登录功能的实现

从今天开始我们来写一个新项目&#xff0c;这个项目是一个完整的校园论坛的项目。主要功能模块&#xff1a;用户登录注册&#xff0c;帖子发布和热帖排行&#xff0c;点赞关注&#xff0c;发送私信&#xff0c;消息通知&#xff0c;社区搜索等。这篇文章我们先试着写一下用户的…

风速预测(七)VMD-CNN-BiLSTM预测模型

目录 往期精彩内容&#xff1a; 前言 1 风速 VMD 分解与可视化 1.1 导入数据 1.2 VMD分解 2 数据集制作与预处理 3 基于Pytorch的VMD CNN-BiLSTM 预测模型 3.1 定义VMD CNN-BiLSTM预测模型 3.2 设置参数&#xff0c;训练模型 4 模型评估与可视化 4.1 结果可视化 4.2…

蓝桥杯-常用STL(三)

常用STL &#x1f388;1.映射&#x1f388;2.map的基础使用&#x1f52d;2.1引入库&#x1f52d;2.2构造一个映射&#x1f52d;2.3插入一对映射&#x1f52d;2.4判断关键字是否存在&#x1f52d;2.5遍历映射&#x1f52d;2.6清空 &#x1f388;1.映射 &#x1f50e;映射是指两个…

[spark] RDD 编程指南(翻译)

Overview 从高层次来看&#xff0c;每个 Spark 应用程序都包含一个driver program&#xff0c;该程序运行用户的main方法并在集群上执行各种并行操作。 Spark 提供的主要抽象是 resilient distributed dataset&#xff08;RDD)&#xff0c;它是跨集群节点分区的元素集合&…

多个版本的Python如何不冲突?

转载文章&#xff0c;防止忘记或删除 转载于&#xff1a;电脑中存在多个版本的Python如何不冲突&#xff1f; - 知乎 (zhihu.com) 如何安装多版本的Python并与之共存&#xff1f; 如果你的工作涉及到Python多版本之间开发或测试&#xff0c;那么请收藏本文&#xff0c; 如果你…

RabbitMQ讲解与整合

RabbitMq安装 类型概念 租户 RabbitMQ 中有一个概念叫做多租户&#xff0c;每一个 RabbitMQ 服务器都能创建出许多虚拟的消息服务器&#xff0c;这些虚拟的消息服务器就是我们所说的虚拟主机&#xff08;virtual host&#xff09;&#xff0c;一般简称为 vhost。 每一个 vhos…

【Java程序设计】【C00331】基于Springboot的驾校预约学习系统(有论文)

基于Springboot的驾校预约学习系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的驾校预约学习系统&#xff0c;本系统有管理员、用户和教练三种角色&#xff1b; 管理员&#xff1a;个人中心、管理员管理、教练…

哈夫曼树的介绍

定义 路径长度&#xff1a;从根结点到该结点所经过的边数。 叶子结点的带权路径长度&#xff1a;叶子结点的权值*路径长度 树的带权路径长度&#xff1a;所有叶子结点的带权路径长度之和 哈夫曼树&#xff1a;带权路径长度最小的树&#xff0c;也称最优二叉树。 构造 反复选…

Scala Intellij编译错误:idea报错xxxx“is already defined as”

今天写scala代码时,Idea报了这样的错误&#xff0c;如下图所示&#xff1a; 一般情况下原因分两种&#xff1a; 第一是我们定义的类或对象重复多次出现&#xff0c;编译器无法确定使用哪个定义。 这通常是由于以下几个原因导致的&#xff1a; 重复定义&#xff1a;在同一个文件…

LNMP架构的源码编译环境下部署Discuz!社区论坛与Wordpress博客

一.编译安装Nginx 1.关闭防火墙 systemctl stop firewalld systemctl disable firewalld setenforce 0 2.安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make 3.创建运行用户 nginx 服务程序默认 以 nobody 身份运行&#xff0c;建议为其创建专门的用户账户&…

飞天使-学以致用-devops知识点4-SpringBoot项目CICD实现

文章目录 代码准备创建jenkins 任务测试推送使用项目里面的jenkinsfile 进行升级操作 代码准备 推送代码到gitlab 代码去叩叮狼教育找 k8s 创建jenkins 任务 创建一个k8s-cicd-demo 流水线任务 将jenkins 里面构建时候的地址还有token&#xff0c; 给到gitlab里面的webhooks…