这一次,吃了Redis的亏,也败给了GPT

news2024/11/23 11:03:43

关注【离心计划】,一起离开地球表面

 

背景

组内有一个系统中有一个延迟任务的需求,关于延迟任务常见的做法有时间轮、延迟MQ还有Redis Zset等方案,关于时间轮,这边小苏有一个大学时候做的demo:

https://github.com/JAYqq/GoDelayTasks

该系统采用的是zset的方案,在系统稳定运行了三年多后,这周出现了一个大面积故障,背后的原因居然是zscan的问题,我们今天就简单复盘一下这次的故障,好好盘一盘zset。

 

zset实现延时任务队列

关于zset的底层数据结构和基本操作,在之前的文章就已经阐述过了,简单来说就是底层由ziplist组织,超过一定阈值(默认128)就改为由skiplist:

【专栏】基础篇03| Redis 花样的数据结构

最常见的延迟任务就是下单,某宝中我们下单未支付后,会倒计时一段时间,到点后订单自动释放;还有完成订单后,超过一定时间就会自动签收。这些都是延迟任务,在zset中,我们将业务类型作为key、订单ID作为member、下单时间+延迟时间作为score,这样的一个zset结构,我们配合zrangeByScore(0,currentTime),就能获取到当前时间应该过期的任务了,简单操作如下:

127.0.0.1:6379> zadd order 100 111
(integer) 1
127.0.0.1:6379> zadd order 120 112
(integer) 1
127.0.0.1:6379> zadd order 140 113
(integer) 1
127.0.0.1:6379> zadd order 170 114
(integer) 1
127.0.0.1:6379> zrangebyscore order 0 130
1) "111"
2) "112"

zrangeByScore在异步线程定时执行就行了,这是延时任务的主动释放。而在组内应用的系统中,还有一个监听消息的机制,当接收到消息后需要取出sessionId,将zset中对应的session元素删除,这边就需要扫描zset所有元素,便用到了zscan命令。

zscan

zscan是一个增量命令,它在官网的定义如下:

所谓增量就是不会一次全部,而是返回一定数量的元素,也就是上面指定的count,然后返回cursor表示扫描到的位置,只要这个cursor不为0就表示扫描没有结束,这就是增量命令最重要的表现形式。

然而,这是我们对增量的理解,但是zset狗在对于元素数量比较少的时候,也就是底层以ziplist组织的时候,会忽视count,一次返回所有元素;而当以skiplist组织的时候,才会返回count个,如果没有传count,默认10个。这也是此次组内系统故障的根因,同事在用zscan的时候并没有传count,但是元素数量超过了128个,导致只扫描了10个后就停止了,代码也没有继续从返回的cursor扫描,导致了zset中存在大量的元素未被删除,被延迟任务队列监控线程通过zrangeByScore扫描到,错误地认为这些元素超时而返回了错误的系统信息。

从源码上看,也可以看出一些端倪

这边看确实默认值是10,但是直到我看到:

当是skiplist的时候,count会默认变成两倍,但是在我的电脑上并没有这个现象,可能是版本差异,但是我找了之前的release描述,没有找到相关的信息,这个问题因为我太饿了就查不下去了(其实是懒

),有读者知道的可以后台私信,感谢~

zset-max-ziplist-entries 3
127.0.0.1:6379> object encoding order
"ziplist"
127.0.0.1:6379> zscan order 0 match "order*" count 5
1) "0"
2)  1) "order-111"
    2) "100"
    3) "order-112"
    4) "110"
    5) "order-113"
    6) "120"
    7) "order-114"
    8) "130"
    9) "order-115"
   10) "140"
   11) "order-116"
   12) "150"
   13) "order-118"
   14) "170"
   15) "order-119"
   16) "180"
   17) "order-120"
   18) "190"
   19) "order-121"
   20) "200"
   21) "order-122"
   22) "210"
   23) "order-123"
   24) "220"
127.0.0.1:6379> zadd order 230 order-124
(integer) 1
127.0.0.1:6379> object encoding order
"skiplist"
127.0.0.1:6379> zscan order 0
1) "5"
2)  1) "order-123"
    2) "220"
    3) "order-116"
    4) "150"
    5) "order-118"
    6) "170"
    7) "order-124"
    8) "230"
    9) "order-121"
   10) "200"
   11) "order-114"
   12) "130"
   13) "order-120"
   14) "190"
   15) "order-115"
   16) "140"
   17) "order-111"
   18) "100"
   19) "order-122"
   20) "210"

发现确实只返回了10个,并且cursor是5,表示并没有结束,至此我们复现了系统的问题,现象也是一致的。

解决方案

方案一:传一个很大的count

方案二:zrange扫描全部,代码内做筛选

方案三:循环zscan,直到cursor为0

业务方案:zrangeByScore扫描到后继续保底

复盘

故障从监控预警到定位问题时间较长,原因在于开发人员并没有直接定位到zscan的问题,并且这部分命令是作为lua脚本执行,调试困难。

流程上看,这种问题无法通过单测发现,确实需要开发人员本身对所用技术的深刻了解,任何流程规则只能降低问题发生概率。

最后,gpt给出的答案确实是生产方案

周末快乐,分享一句最近看到的诗

欲买桂花同载酒,终不似,少年游

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

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

相关文章

Cacti监控远程linux机器配置(被监控端)

一、被监控机安装snmp yum -y install snmp二、被监控机的配置 vi /etc/snmp/snmpd.conf做以下更改: 1、找到com2sec notConfigUser default public 改为:com2sec notConfigUser 192.168.1.1(改成监控服务器的ip) public 2、找到acce…

【hello Linux】进程概念(上)

目录 1.操作系统(OS) 2. 进程 2.1 基本概念 2.2 task_struct 内的属性字段 2.3 查看进程 2.4 查看进程的PID及PPID 2.5 杀死进程 2.6 以文件的方式查看进程 2.7 查看退出码 2.8 上下文数据 下面介绍两个较为方便的快捷键: Linux🌷…

语义分割新范式:上海 AI Lab 联合北邮、商汤提出StructToken

来源:投稿 作者:xin 编辑:学姐 Motivation 本文将当前语义分割的方法分为两类,一类是静态逐像素分类方法(static per-pixel classification),另一类为动态逐像素分类方法(dynamic p…

Ubuntu备份与恢复

Ref: create-backup-image-of-running-ubuntu Linux中我们有权访问所有系统文件,因此,最简单且直接的备份方法是将整个根目录打包: sudo su tar -cpzf /path/to/backup.tar.gz --exclude/tmp --one-file-system /其中-cpzf 表示建立压缩归档…

MQTT 持久会话与 Clean Session

1. 会话(session) 我们将从客户端向服务端发起 MQTT 连接请求开始,到连接中断直到会话过期为止的消息收发序列称之为会话。会话是服务端和客户端的一个连接,进行消息交互前必须先建立会话。 2. 会话的生命周期 MQTT v3.1.1会话…

003_螺旋矩阵

力扣54和59题 54.顺时针打印矩阵 题目: 思路:将矩阵分为若干层,首先打印最外层的元素,然后一直往里打印 对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于(top,left),右下角位于…

Axios请求(对于ajax的二次封装)——Axios取消请求、请求体编码

Axios请求(对于ajax的二次封装)——Axios取消请求、请求体编码知识回调(不懂就看这儿!)场景复现核心干货axios取消请求AbortControllerCancelToken deprecated请求体编码浏览器qs库编码数据ES6库方法node.jsQuery stri…

【神经网络】tensorflow实验3--NumPy科学计算库

目录 1. 实验目的 2. 实验内容 3. 实验过程 题目一: ① 代码 ② 实验结果 题目二: ① 代码 ② 实验结果 题目三: ​编辑 ① 代码 ② 实验结果 5. 实验小结 ① 实验过程中遇到了哪些问题,你是如何解决的? …

Android引入Apollo(阿波罗)

程序猿日常 记Android项目引入Apollo(阿波罗)上源码 apollo开发分支 应用 Apollo(阿波罗)客户端会管理好应用的后台GraphQL数据 之前网络请求使用RetrofitOkHttp 改成使用ApolloOkHttp 引入 1.对应的module的build.gradle中添加 id("com.apollographql.apollo3&qu…

【计算机系统概论Yale.patt】第一章

文章目录1. 计算机是简单部件的系统组合1.1 计算机组成1.1.1 编码体系1.1.2 晶体管构建微处理器1.1.3 冯诺依曼机1.1.4 LC-3机(冯诺依曼机实现)1.1.5 LC-3编程机器语言编程汇编语言编程输入输出信息问题两个重要机制栈和数据转换示例:计算器1.2 两个重要理念1.2.1 抽…

Linux基础篇(三)常见指令

目录 一、创建文件和目录 二、命令详解 0. 命令和选项 1. ls命令 2. cd命令 3. touch命令 4. mkdir命令 5. tree命令 6. rmdir命令 7. rm命令 8. man 9. nano 10. cat命令 11. cp 命令 12. mv 命令 13. echo命令 14. more命令 15. less命令 16. Ctrl C 17. head 命令 18. tail…

台灯的种类有哪些?国内热门护眼灯品牌推荐

台灯是我们日常生活中常见的电器之一,台灯不仅可以为人们照明,还可以用来家居装饰,根据人们不用的需求,台灯的种类也很多,有书房台灯、读写台灯、工艺台灯。 书房台灯:灯光的局部照明效果,以书写…

禅道OpenAI更新至1.2版本,超多实用功能惊喜上线!

广受欢迎的禅道OpenAI插件近日成功发布,截至目前已更新至1.2版本。 截至本版本发布,禅道OpenAI已经拥有了神奇海螺(ChatGPT聊天)、需求润色、任务润色、Bug润色及本次的需求一键生成用例功能,仍有更多实用的新功能正在…

Sentinel 工作主流程

Overview 在 Sentinel 里面,所有的资源都对应一个资源名称以及一个 Entry。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 API 显式创建;每一个 Entry 创建的时候,同时也会创建一系列功能插槽(…

2023年第1季社区Task挑战赛开启,等你来战!

社区Task挑战赛是面向社区开发者开展的代码或教程征集活动。该挑战赛为社区中热爱FISCO BCOS及周边组件的开发者提供了探索区块链技术、挑战技术难题的舞台。该挑战赛去年在社区成功举办了3季,共吸引了数百名开发者报名。 前3季都有哪些有趣的作品? 在…

【图数据挖掘】— 子图同构问题、单射函数和双射函数、同构(isomorphic)和同态(homomorphism)

子图同构问题 子图同构(Subgraph Isomorphism)是指在图论中,两个图之间是否存在一种关系,使得其中一个图的顶点集合和边集合可以通过对应的方式映射到另一个图的顶点集合和边集合上,且保持原来的边和顶点的关系不变。…

如何设计一个安全的对外接口?

对外接口安全措施的作用主要体现在两个方面,一方面是如何保证数据在传输过程中的安全性,另一方面是数据已经到达服务器端,服务器端如何识别数据。 1. 数据加密 数据在传输过程中是很容易被抓包的,如果直接传输,数据可…

elasticsearch 核心概念

1.近实时(Near Real Time,NRT) elasticsearch 是一个近实时的搜索和分析平台,这意味着从索引文档到可搜索文档都会有一段微小的延迟(通常是1s以内)。这种延迟主要是因为 elasticsearch 需要进行数据刷新和索引更新。 …

远程代码执行渗透与防御

远程代码执行渗透与防御1.简介2.PHP RCE常见函数3.靶场练习4.防御姿势1.简介 远程代码执行漏洞又叫命令注入漏洞 命令注入是一种攻击,其目标是通过易受攻击的应用程序在主机操作系统上执行任意命令。 当应用程序将不安全的用户提供的数据(表单、cookie…

jQuery 基础入门速成上篇

jQuery 是目前使用最广泛的 javascript 函数库。提到 jQuery 你可能知道这句英文 : ———— Write Less,Do More ( 写的少,做的多 ) 引入jQuery jQuery是一个函数库,一个 js 文件,页面可以使用 script标签 引入使用&a…