redis五大类型分析--list(1)
此篇为对redis五大数据类型中list的分析,希望能有所帮助
List API
listTypePush函数
void listTypePush(robj *subject, robj *value, int where) {/* 检查编码类型是否为 quicklist (快速列表) */if (subject->encoding == OBJ_ENCODING_QUICKLIST) {/* 根据参数 where 选择插入位置,由 pos 保存插入位置信息 */int pos = (where == LIST_HEAD) ? QUICKLIST_HEAD : QUICKLIST_TAIL;/* value 为整数编码 */if (value->encoding == OBJ_ENCODING_INT) {/* 将 value 先转换为字符串 */char buf[32];ll2string(buf, 32, (long)value->ptr);/* 将元素插入列表 */quicklistPush(subject->ptr, buf, strlen(buf), pos);/* value 为字符串编码 */} else {quicklistPush(subject->ptr, value->ptr, sdslen(value->ptr), pos);}} else {serverPanic("Unknown list encoding");}
}
分析:
该函数将一个元素插入到指定的列表对象 'subject', 插入位置由 'where' 决定是在列表头部还是尾部插入,调用者不需要自己来增加 'value' 的 refcount,该函数会负责处理。
作用:
实现命令函数pushGenericCommand中会用到
/* 读取输入的元素,并向列表插入元素 */for (j = 2; j < c->argc; j++) {listTypePush(lobj,c->argv[j],where);/* 脏数据 + 1,即缓存中未保存到本地的数据 */server.dirty++;}
实现 lmove 命令中向目的列表(destination)插入元素中会用到
/* 向列表中插入元素 */listTypePush(dstobj,value,where);
listPopSaver函数(用于给列表弹出的元素创建副本的函数)
void *listPopSaver(unsigned char *data, size_t sz) {return createStringObject((char*)data,sz);
}
示例:
给quicklistPopCustom传参用到
/* 从列表中弹出元素 */if (quicklistPopCustom(subject->ptr, ql_where, (unsigned char **)&value,NULL, &vlong, listPopSaver))
listTypePop函数(弹出列表元素的通用实现函数)
robj *listTypePop(robj *subject, int where) {long long vlong;robj *value = NULL;/* 根据参数 where 选择插入位置,由 ql_where 保存插入位置信息 */int ql_where = where == LIST_HEAD ? QUICKLIST_HEAD : QUICKLIST_TAIL;/* 检查编码类型是否为 quicklist (快速列表) */if (subject->encoding == OBJ_ENCODING_QUICKLIST) {/* 从列表中弹出元素 */if (quicklistPopCustom(subject->ptr, ql_where, (unsigned char **)&value,NULL, &vlong, listPopSaver)) {/* 如果 value 为 NULL ,则弹出元素被保存在 vlong 中(若不为 NULL 则说明保存在 value 中)* 则用 vlong 创建一个字符串对象并让 value 对其引用 */if (!value)value = createStringObjectFromLongLong(vlong);}} else {serverPanic("Unknown list encoding");}return value;
}
示例:
popGenericCommand函数,弹出一个元素
/* 弹出一个元素,这是 pop 的原始操作,会向客户端回复一个字符串 */value = listTypePop(o,where);
listTypeLength函数(获取列表长度(元素总数))
unsigned long listTypeLength(const robj *subject) {if (subject->encoding == OBJ_ENCODING_QUICKLIST) {return quicklistCount(subject->ptr);} else {serverPanic("Unknown list encoding");}
}
listTypeInitIterator函数(在指定的索引处初始化一个列表迭代器)
listTypeIterator *listTypeInitIterator(robj *subject, long index,unsigned char direction) {/* 给列表迭代器分配内存空间 */listTypeIterator *li = zmalloc(sizeof(listTypeIterator));/* 初始化列表迭代器 */li->subject = subject;li->encoding = subject->encoding;li->direction = direction;li->iter = NULL;/* LIST_HEAD means start at TAIL and move *towards* head.* LIST_TAIL means start at HEAD and move *towards* tail. *//* LIST_HEAD 意味着从列表尾部开始,并向头部移动。* LIST_TAIL 表示从列表头部开始,并向尾部移动 */int iter_direction =direction == LIST_HEAD ? AL_START_TAIL : AL_START_HEAD;/* 检查编码类型是否为 quicklist (快速列表) */if (li->encoding == OBJ_ENCODING_QUICKLIST) {/* 初始化一个 quicklist 节点的迭代器,并且该迭代器指向列表的第 index 个元素,* 虽然用词是”指向“但是迭代器并不是一个指针,而是个结构体,它记录的元素信息是列表第 index 个元素 */li->iter = quicklistGetIteratorAtIdx(li->subject->ptr,iter_direction, index);} else {serverPanic("Unknown list encoding");}return li;
}
用处:
linsertCommand函数中用于遍历查找,初始化迭代器;在addListRangeReply函数中初始化范围起点位置的迭代器
listTypeSetIteratorDirection函数(设置迭代器的方向 )
void listTypeSetIteratorDirection(listTypeIterator *li, unsigned char direction) {li->direction = direction;int dir = direction == LIST_HEAD ? AL_START_TAIL : AL_START_HEAD;quicklistSetDirection(li->iter, dir);
}
listTypeReleaseIterator函数(释放迭代器)
void listTypeReleaseIterator(listTypeIterator *li) {quicklistReleaseIterator(li->iter);zfree(li);//redis定义的一个函数,在free函数的基础上有改变
}
基本上跟在listTypeInitIterator函数后面,释放迭代器
listTypeNext函数
int listTypeNext(listTypeIterator *li, listTypeEntry *entry) {/* Protect from converting when iterating *//* 保护迭代时编码不被转换,则需要迭代器记录的编码类型和迭代器指向的列表对象编码一致 */serverAssert(li->subject->encoding == li->encoding);/* 将参数 li 赋值给参数 entry 的迭代器成员 */entry->li = li;/* 检查编码类型是否为 quicklist (快速列表) */if (li->encoding == OBJ_ENCODING_QUICKLIST) {/* 调用 quicklistNext 函数获取下一个元素,* 元素 (quicklistEntry) 保存在 entry->entry 中,并推进迭代器位置* 如果 下一个元素存在,该函数返回1,否则返回0 */return quicklistNext(li->iter, &entry->entry);} else {serverPanic("Unknown list encoding");}return 0;
}
分析:
获取迭代器指向元素的下一个元素,并推进迭代器的位置(推进方向由迭代器成员 direction 决定)。 如果 entry(下一个元素) 存在,返回1,否则返回0
用处:
linsertCommand函数中用于遍历查找,在addListRangeReply函数中设置迭代器的范围起点位置
总结:
本篇分析了listpush,popsaver,poplength函数,对列表弹出元素和计算列表长度的功能进行分析,同时还分析了关于迭代器初始化,设置方向,释放和获取迭代器下一个元素的函数,对迭代器的功能进行分析。
相关文章:
redis五大类型分析--list(1)
此篇为对redis五大数据类型中list的分析,希望能有所帮助 List API listTypePush函数 void listTypePush(robj *subject, robj *value, int where) {/* 检查编码类型是否为 quicklist (快速列表) */if (subject->encoding OBJ_ENCODING_QUICKLIST) {/* 根据参数…...
【多重信号分类】超分辨率测向方法——依赖于将观测空间分解为噪声子空间和源/信号子空间的方法具有高分辨率(HR)并产生准确的估计(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【Express.js】集成Websocket
集成websocket 本节我们介绍在如何在 express 中集成 websocket。 WebSocket 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。 准备工作 创建一个 express.js 项目&a…...
MachineLearningWu_14/P65-P69_Multiclass
x.1 Multiclass多分类问题 对于分类问题,往往指的是二分类问题,而对于二分类的decision boundary较为简单,而实际生活中会有很多问题是多分类问题,例如MNIST手写数字识别, 从特征空间上来看,二分类和多分类…...
深入理解高并发编程 - SimpleDateFormat 类的线程安全问题
1、重现与解决 1.1、重现 import java.text.SimpleDateFormat; import java.util.Date;public class UnsafeSimpleDateFormatExample {public static void main(String[] args) {SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Runnable task…...
接口幂等性实现方式
优质博文:IT-BLOG-CN 幂等 操作的特点是一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。幂等函数或幂等方法是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态&am…...
redis高可用之持久化
目录 一、Redis 高可用的相关知识 1)什么是高可用 2)Redis的高可用技术 3)持久化的功能 4)redis持久化的方式 二、RDB持久化 1)RDB持久化的触发方式 (1)手动触发 (2&…...
Cocos Creator 3.8 后期效果 Shader 编写(2/2) 进阶篇
前言 在上一篇文章中,麒麟子给大家分享了如何在 Cocos Creator 3.8 中的自定义管线中,添加属于自己的后期效果 Shader。 但基于 BlitScreen 的方案,我们只能编写最简单后效 Shader,如果我们想要支持更多复杂的 Shader,…...
【JS自用模板】自动点击选课的操作模板
以激动点击课程为案例复习一下基本前端,容易涉及的问题包括如何提取object类的数字,setTimeout为什么不起作用? 具体思路是,此处会立刻选中符合条件的页面元素打开,然后1小时后会刷新页面,相应地播放页面也…...
TENNECO EDI 项目——X12与XML之间的转换
近期为了帮助广大用户更好地使用 EDI 系统,我们根据以往的项目实施经验,将成熟的 EDI 项目进行开源。用户安装好知行之桥EDI系统之后,只需要下载我们整理好的示例代码,并放置在知行之桥指定的工作区中,即可开始使用。 …...
C++项目:在线五子棋对战(网页版)
项目介绍 本项⽬主要实现⼀个⽹⻚版的五⼦棋对战游戏,其主要⽀持以下核⼼功能: • 用户管理:实现用户注册,用户登录、获取用户信息、用户天梯分数记录、用户比赛场次记录等。 • 匹配对战:实现两个玩家在网页端根据天梯分数匹配游戏对⼿&…...
flutter遇到的小问题记录
flutter-getx的Get.bottomSheet组件改变高度 Get.bottomSheet( isScrollControlled: true,) isScrollControlled: true 就是控制高度 (无语) 截取视频第一针 返回的是本地url 或者Uint8List的数据 String? videoStr await VideoThumbnail.thumbnailFile(video: videoPath,…...
Golang bitset 基本使用
安装: go get github.com/bits-and-blooms/bitset下面代码把fmtx换成fmt就行 //------------基本操作------------//构建一个64bit长度的bitsetb : bitset.New(64)//放入一个数b.Set(10)fmtx.Println("add-10:", b.DumpAsBits()) // 0000000…...
sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现
1. 二级分组需求 先按照一个字段分组,在按照 第二个字段分组。之后,如果 这个 二级分组中的数据,是 > 1条的。就筛选出来。 比如: 先按照 站点分组,再按照 设备分组, 即:如果站点上配置了…...
业务中如何过滤敏感词
在我们访问网站的时候,如果发现我们发布的内容有色情暴力的东西等等,会屏蔽掉,这种行为就是过滤敏感词。 从技术层面实现起来,其实比较简单,因为我们输入的内容就是一个大型的字符串,我们要调用某些api来判…...
用服务器搭建网站需要做什么
网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。不同领域的网页设计,网页图形设计,界面设计,创作,其中包括标准化的代码和专有软件,用户体验设计和搜索引擎优化。许多人…...
clickhouse 删除操作
OLAP 数据库设计的宗旨在于分析适合一次插入多次查询的业务场景,市面上成熟的 AP 数据库在更新和删除操作上支持的均不是很好,当然 clickhouse 也不例外。但是不友好不代表不支持,本文主要介绍在 clickhouse 中如何实现数据的删除,…...
C 语言中,「.」与「->」有什么区别?
使用“.”的话,只需要声明一个结构体。格式是结构体类型名结构体名。然后通过结构体名加上“.”再加上域名,就可以引用结构体的域了。因为结构体的内存是自动分配的,就像使用int a;一样。而使用“->”的话,需要声明一个结构体的…...
github pages 用法详解 发布自己的网站
github pages 基础用法 URL 规则 假设你的 github 帐号为 mygithub,需要发布的仓库名为 myrepo,那么 pages 的 URL 为: https://mygithub.github.io/myrepo 添加内容 用任意编辑器写好(或者生成)标准的网页内容&a…...
坤简炫酷的JQuery轮播图插件
介绍: 找到了一个炫酷的JQuery轮播图插件,只需要配置三四行代码就可以实现很多二维三维炫酷的切换效果。 视频效果及教程: https://www.bilibili.com/video/BV1Fu4y1d776/ 代码: https://github.com/w-x-x-w/AwesomeWeb 使用…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
