上海做网站的费用/hao123上网从这里开始官方
此篇为对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 使用…...

C# 条件编译
C# 条件编译 C# 条件编译:根据不同的需求,编译生成不同的程序版本,条件编译是一种编译预处理命令,它是在编译代码之前对源代码进行处理。它可以根据条件,决定是否编译某段代码 条件编译的三种形式: 第一种…...

IntelliJ IDEA如何重新弹出git身份验证窗口
1、点击File菜单—>点击Settings—>点击Appearance & Behavior—>点击System Settings—>点击Passwords—>选中Do not save, forget passwords after restart—>点击Apply—>点击OK,如下所示: 2、重启IntelliJ IDEA—>通过g…...

【雕爷学编程】Arduino动手做(200)---WS2812B幻彩LED灯带4
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...

【雕爷学编程】Arduino动手做(201)---DFRobot 行空板03
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...

Spring中Bean的“一生”(生命周期)
文章目录 一、图解二、文字解析总结 一、图解 >注:处于同一行的执行顺序是从左往右 二、文字解析 SpringBean的生命周期总体分为四个阶段:实例化>属性注入>初始化>销毁 Step1 实例化Bean:根据配置文件中Bean的定义,…...

安卓:LitePal操作数据库
目录 一、LitePal介绍 常用方法: 1、插入数据: 2、更新数据: 3、删除数据: 4、查询数据: 二、LitePal的基本用法: 1、集成LitePal: 2、创建LitePal配置文件: 3、创建模型类…...

【JavaEE初阶】了解JVM
文章目录 一. JVM内存区域划分二. JVM类加载机制2.1 类加载整体流程2.2 类加载的时机2.3 双亲委派模型(经典) 三. JVM垃圾回收机制(GC)3.1 GC实际工作过程3.1.1 找到垃圾/判定垃圾1. 引用计数(不是java的做法,Python/PHP)2. 可达性分析(Java的做法) 3.1.2 清理垃圾1. 标记清除2…...

基于vue2.0和elementUi的vue农历日期组件vue-jlunar-datepicker(插件)
vue-jlunar-datepicker(插件) vue实现农历日历插件——vue-jlunar-datepicker插件 这个插件本身是基于vue2.0和elementUi框架来实现的。 安装 vue-jlunar-datepicker 插件 npm install vue-jlunar-datepicker --save // 如果安装过程中,出现…...

Python爬虫——selenium_元素定位
元素定位:自动化要做的就是模拟鼠标和键盘来操作这些元素,点击,输入等等。操作这些元素前首先要找到它们,WebDriver提供很多定位元素的方法 from selenium import webdriver# 创建浏览器对象 path files/chromedriver.exe brows…...

短视频内容平台(如TikTok、Instagram Reel、YouTube Shorts)的系统设计
现在,短视频内容已成为新趋势,每个人都在从TikTok、Instagram、YouTube等平台上消费这些内容。让我们看看如何为TikTok创建一个系统。 这样的应用程序看起来很小,但在后台有很多事情正在进行。以下是相关的挑战: •由于该应用程序…...