回顾Redis之对象与数据结构

25_StringRedisTemplate操作Redis 本文主要介绍了 StringRedisTemplate 对 Redis 常见数据结构的操作方法。Spring Data Redis 提供的 StringRedisTemplate,其 key 和 value 序列化默认为 String 方式,但操作对象数据时需手动进行 JSON 序列化与反序列化。 阅读详情

引言

Redis是一款基于键值对的数据结构存储系统,它的特点是基于内存操作、单线程处理命令、IO多路复用模型处理网络请求、键值对存储与简单丰富的数据结构等等

这篇文章主要围绕Redis中的对象与数据结构来详细说明键值对存储与简单丰富的数据结构这两大特点

Redis中的数据以Key,Value键值对的形式存储在字典中,字典的实现是哈希表

键Key只能使用字符串对象来表示,值Value能够使用其他所有对象

对象与数据结构

Redis中存在丰富的对象,常用的对象(数据类型)有字符串对象string、列表对象list、散列对象hash、集合对象set、有序集合对象zset等

还有其他的数据类型如Bitmap、Hyperloglog、Geospatial、布隆过滤器等,但这篇文章只涉及常用的对象,其他数据类型再以后的文章中再展开说明

  • redis中的对象RedisObject由类型、编码、引用次数、lru、指向编码使用的数据结构对象构成

  • 类型标识这个对象是什么类型对象

  • 比如字符串、列表、哈希、集合、有序集合等

  • 编码表示构成对应类型对象时使用哪种数据结构

  • 引用次数表示这个对象被引用了多少次

  • redis内存回收使用引用计数法,回收引用次数为0的对象 redis只依赖字符串对象,而不存在循环依赖所以不存在循环引用,因此可以使用引用计数法

  • lru记录这个对象最近被调用的时间,当空间回收算法使用lru时会优先回收很久未用的对象(后续删除回收的文章会介绍)

数据结构

sds简单动态字符串

sds使用字节数组维护,len记录字符串长度(表示结尾的'\0'不算),free表示字节数组中空闲的长度

​在添加元素前会判断数组长度是否足够,不够则会进行扩容;扩容有空间预分配策略,会留有一部分空闲空间

如果下次修改字符串未超出数组长度就能够直接修改,节省了扩容的开销

hashtable字典

字典使用哈希表实现,哈希表的原理本篇文章不会详细概述

哈希冲突使用链地址法解决,查找时先通过 hash%数组长度-1 来获取索引,得到索引后再遍历链表节点,如果是新增则直接使用头插法,插入链表头部

​为了防止大字典扩容时发生阻塞,字典中哈希表的扩容是循序渐进的,在发生扩容时会有俩个哈希表

​旧哈希表和新哈希表中都可能存储数据,再收到hget等请求时先在旧哈希表中查找,找到了就顺便把它迁移到新哈希表中;在旧哈希表中没找到就去新哈希表中找

在完成迁移时,新哈希表将旧哈希表替换

skiplist跳表

跳表维护多层级的有序链表,利用高层能够快速达到后续节点,实现简单,维护方便,增删改查时间复杂度平均log n

​比如查找值为2.0的节点,查找顺序为图中虚线

先找到虚拟头节点,从当前维护的最高层(L5)开始寻找,往后找到o3对象值为3.0,说明已经找过头了,于是要去下一层进行寻找;来到L4先后遍历,o1对象值为1.0,比目标值2.0小,说明没有目标值在o1对象后面,于是来到o1对象L4层;继续在o1对象L4向后遍历,发现o3值为3.0大于目标值,于是降层来到o1对象L3层;L3层后面也是o3于是继续降层,来到L2层,L2层向后遍历为o2对象,值为2.0并比较o2对象相同说明找到了

从维护的最高层开始查询,查询为空或者查询值大于目标值则降层,当前在最后一层还需要降层说明找不到

当排序值相同时,按照对象大小排序,这里的对象都是字符串对象

增加节点时的层数是随机生成的,越高层几率越小;其他修改操作,也是通过查询再进行,同时还要维护一些如最高层级等其他属性

intset整数集合

intset 维护了一个有序,无重复的数组

在实现上使用数组、长度(记录元素数量)和编码(编码能够标识元素类型,如16、32、64位的整型)

​当加入的元素为当前数组内不存在的高位整型时(比如数组中都是32位整型,此时加入一个64位整型)发生升级:先申请内存重分配,再将旧元素移动到对应位置上,然后加入新元素同时修改编码,当删除高位整型时不会发生降级

intset的升级有效的节约内存,当set对象都为整型且数据量较小时使用intset实现以此来节约内存

ziplist压缩列表

ziplist用连续空间的节点构成,节点由记录前驱节点偏移量(逆序遍历)、编码(字节数组或整型的编码)、内容(内容可以是字节数组或整型)组成

​因为ziplist的内容不是固定的,比如记录前驱节点偏移量是可变长的,这会影响节点的长度,又因为ziplist是空间连续的,这会导致后续的节点空间都要变动,被称为连锁更新(发生的概率小)

为了节省空间,用于数量量小场景下列表、哈希、有序集合的实现

quicklist快速列表

快速列表可以当作双向链表,只不过节点使用ziplist,常用来实现数据量大场景下的列表对象

对象

说明:

下文中数据量代表着占用字节情况和数据元素数量

本篇文章不介绍各个对象的命令使用规则,需要学习命令的同学可以去官网查看

字符串对象

字符串对象string由sds简单动态字符串来实现

  • sds有不同的编码:int、embstr、row

  • int 用来存储整型字符串,计算时可能发生整型与字符串的转换

  • embstr 用来存储短的字符串,只分配一次内存,分配内存时同时分配redisobject和sds

  • row 用来存储长字符串,分配内存时需要分配两次:redisobject、sds

字符串对象是Redis中最常用的对象,也是唯一会被其他对象依赖使用的对象

字符串对象常见的使用场景:整存整取的缓存、计数器、分布式锁

列表对象

列表对象list是一个队列,可以操作队头队尾,由ziplist或quicklist来实现

数据量小时使用ziplist,数据量大时使用quicklist( linkedlist+ziplist )

列表的使用场景是FIFO队列保证元素访问顺序

哈希对象

哈希对象hash是维护KV键值对的无序数据结构,由ziplist或hashtable来实现

数据量少使用ziplist、数据量大使用hashtable

哈希的使用场景是缓存的部分存取(比如一个大礼包下有A商品B商品等)

集合对象

集合对象set的特点是无序、无重,由intset或hashtable来实现

数据量少且数据为整型使用intset、数据量大或数据不为整型使用hashtable且值永远为null

集合的使用场景是唯一性元素或交集并集(共同关注、可能认识)等(无序、无重复)

有序集合对象

有序集合对象zset是有序、无重的数据结构,由ziplist或skiplist + hashtable实现

数据量少时使用ziplist、数据量大时使用skiplist + hashtable(为了满足根据对象查询分指常量级功能,共享对象,不造成内存开销)

有序集合的使用场景是排行榜、关注程度榜单等(有序、无重复)

总结

本篇文章围绕Redis以键值对存储、丰富多元的数据结构为特点详细介绍了Redis中的对象与数据结构

对象由类型、编码、数据结构指针等构成

为了节省空间,每种类型的对象都有多种编码类型的数据结构能够实现

  • 字符串对象常用来做缓存、分布式锁、计数器等,被其他对象依赖使用

  • 由sds实现主要有int、embstr、row三种编码来处理不同类型的字符串,embstr处理短字符串优化内存分配

  • sds是动态字符串,利用空间预分配策略在修改不超过数组长度情况下可以不需要进行扩容,节省开销

  • 列表对象常用来维护队列元素有序性

  • 当数据量小时使用压缩列表ziplist实现,数据量大时使用快速列表quicklist实现

  • 压缩列表使用连续空间,节点中存储可以时字符串也可以是整型

  • 快速列表则可以当作链表,节点为压缩列表

  • 哈希对象常用来维护部分存取的缓存

  • 当数据量小时使用压缩列表zpilist实现,数据量大时使用哈希表hashtable实现

  • 哈希表为了防止阻塞,在扩容时使用新旧两个哈希表存储元素,在处理命令的同时完成迁移

  • 集合对象有无序、无重的特点,常用来做唯一、交集(共同好友)、并集(可能认识)

  • 当数据量小且元素都为整型时使用整型集合intset实现,当数据量大使用哈希表实现

  • 整型集合有不同的编码形式,充分节省了空间;使用哈希表时Value为空

  • 有序集合对象有有序、无重的特点,常用来做排行榜

  • 当数据量小时使用压缩列表实现;当数据量大时使用跳表skiplist+哈希表实现,哈希表保存K对象V比较值

  • 跳表是多层级有序的链表,平均时间复杂度在log n,简单易维护

手推反向传播+numpy实现 反向传播的重要性不必多说,手推也是必备基础,大厂面试要求用numpy实现一下BP也是经常的事。下面以一个简单的两层网络为例(简单到连bias都没有的那种),真·手推反向传播+numpy实现。 说明: input:输入 net_h:隐层 S(x):sigmoid简写 SD(x):sigmoid导数的简写 out_h:隐层经过sigmoid激活的输出 net_o:输出层 out_o:经过经过sigmoid激活的输出层,也就是最后的输出 target(简写t1、t2):Ground... 阅读详情

相关推荐

LTE信令流程——切换

LTE信令流程 切换 切换是由基站发起的,不同于小区重选,小区重选是由UE发起的。 基站利用移动性管理算法给UE下发测量任务,在RRC重配置消息中携带MeasConfig信元给UE下发测量配置 切换有三种场景: 同一基站内不同小区的切换 不同基站间基于X2的切换(MME不变) 不同基站间基于S1的切换(MME/SGW可能改变) 1. 同一基站内不同小区的切换 连接态的UE在一个基站的不同小区之间移动 UE上报合适的测量报告(Measure Reports),触发基站切换 基站下发切换命令给UE,

Hxx的博客 1万+

redis五种数据类型用法

1.字符串 基础用法:

qq_32256907的博客 188

如何读懂CiteSpace图谱?科研小白必看的节点颜色/年轮/聚类解读手册

本文详细解析CiteSpace图谱的核心视觉元素,包括节点颜色、年轮和聚类标识,帮助科研人员准确解读数据分析结果。通过生物医学案例展示如何从图谱中识别关键文献和研究趋势,提供五步系统解读法和常见错误规避策略,助力科研小白快速掌握文献计量分析技巧。

weixin_29179311的博客 316

Redis五种基本数据类型的底层实现

redis五种基本类型可以涵盖项目中大多数的使用场景,而它们的底层实现在面试的过程中也是提问的提问的比较多的,今天就花时间来深入理解一下这五种基本数据类型的底层实现吧!

qq_66452396的博客 795

ZYNQ开发(2)在Linux系统层上PL-PS通过AXI-DMA传输数据详细步骤及注意事项

参考的网络资料 https://github.com/bperez77/xilinx_axidma/tree/master https://gitlab.gnome.org/HosseinBeheshti/UlteraZed7EV/-/tree/master/petalinux/xilinx_axidma https://www.icode9.com/content-3-925319.html https://blog.youkuaiyun.com/weixin_38218267/article/details/1

aizaiyueye的专栏 3448

DIC新手避坑指南:压缩实验中的应变测量常见错误与数据校验技巧

本文为DIC技术新手提供了压缩实验中应变测量的全面避坑指南。文章系统梳理了从试样尺寸录入、散斑质量到数据后处理中应变方向与符号混淆、数据插值对齐等常见错误,并分享了基于MATLAB的自动化数据校验与可视化对比技巧,帮助建立可靠的实验数据分析SOP,确保DIC测量结果的准确性。

weixin_29313423的博客 113

Redis常见问题

Redis数据结构 Redis对象类型包括String,Map,List,Set,Zset。String根据字符串长度有两种编码格式,短串使用emstr,长串使用emstr,emstr只会调用一次内存分配函数进行内存分配,row两次内存分配函数调用,分配空间给RedisObject和sdshdr。Map底层由HashTable实现,List使用双向无环链表LinkedList,可以在链表两端进行操作。set底层由HashTable进行实现。Zset使用SkipList进行实现。在数据量少的时候,Ma...

weixin_42582131的博客 256

Opencv2.4.9源码分析——HoughCircles

图形可以用一些参数进行表示,标准霍夫变换的原理就是把图像空间转换成参数空间(即霍夫空间),例如霍夫变换的直线检测就是在距离-角度空间内进行检测。圆可以表示成: (x-a)2+(y-b)2=r2                   (1) 其中a和b表示圆心坐标,r表示圆半径,因此霍夫变换的圆检测就是在这三个参数组成的三维空间内进行检测。 原则上,霍夫变换可以检测任何形状。但复杂的形状需要的

赵春江的专栏 3万+

Redis-----第一部分 数据结构与对象

第一部分 数据结构与对象 文章目录第一部分 数据结构与对象@[toc]1. 简单动态字符串(1). SDS的定义(2). SDS和C字符串的区别1). 获取字符串长度2). 杜绝缓冲区溢出3). 减少修改字符串时带来的内存充分配次数1>. 空间预分配2>. 惰性空间释放4). 二进制安全5). 兼容部分C字符串函数2. 链表(1). 链表和链表节点的实现3. 字典(1). 字典的实现...

Benjalin_76_84的博客 1228

《QGIS快速入门与应用基础》021:插件仓库 URL 获取与添加

详细介绍了在QGIS中添加第三方插件仓库的方法。首先强调必须从官方推荐、开源社区等可靠渠道获取插件仓库URL以确保安全性,并列出了4类可信获取渠道。文章分步骤讲解了URL添加流程,包括打开插件管理器设置面板、填写仓库信息、刷新缓存验证等操作。针对常见问题如URL格式错误、连接失败等提供了具体解决方案。最后总结指出,成功添加第三方仓库后即可直接搜索安装各类专业插件,从而扩展QGIS功能边界。全文注重实操指导,特别适合需要安装行业专用插件的QGIS用户参考。

LuckyHanMo的博客 465

基于高斯两步移动搜寻法(2SFCA)的城市绿地可达性分析

第二步,对于每一个街道i,给定空间距离阈值d0,便形成另一个空间作用域,同样对于落在空间作用域内的每块绿地l的供给比率(Rl)利用高斯方程赋以权重,然后对这些加权后的供给比率(Rl)进行加和,便得到每个街道i的绿地可达性Ai。图3与图4是高斯两步移动搜索法的示例。在图3中,以d0为阈值,有1、2、3 三个街道中心点落在了绿地a的空间作用域内。同样在图4中,以d0为阈值,有a、c两个绿地中心点落在了街道2的空间作用域内,根据公式(3),对a、c高斯方程加权后的供需比率进行累加,便得到了街道2 的绿地可达性。

2301_77310370的博客 2404

重点回顾【Redis设计与实现】第一部分 数据结构与对象

Redis数据库里面的每个键值对(key-value pair)都是由对象(object)组成的,其中: ⚪ 数据库键总是一个字符串对象(string object); ⚪ 而数据库键的值则可以是字符串对象、列表对象(list object)、哈希对象(hash object)、集合对象(set object)、有序集合对象(sorted set object)这五种对象中的其中一种。 一、简单动态字符串 ???? Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simp

dangzefei的博客 598

五、MT8168 音频驱动之SPEAKER

本章主要讲解MT8168平台的内部SPEAKER驱动配置。分为HP接法和LINE OUT接法。2.1.3 audio_custom_exp.h设置。2.1.4 mixer_paths.xml设置。2.2.3 mixer_paths.xml设置。2.1.2 ProjectConfig 设置。2.2.2 ProjectConfig 设置。2.2.1 deconfig设置。2.1.1 DTS设置。......

Joon2020的博客 1664

《深入理解redis》之二:高级键管理与数据结构

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33834679的博客 316

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Redis中的RDB持久化——《Redis设计与实现》读书笔记

RDB持久化图片源文件 RDB持久化Xmind源文件 读者可以查看我之前的一些笔记,包含有文字的描述 Redis中的压缩列表ziplist——《Redis设计与实现》读书笔记 Redis中的字典——《Redis设计与实现》读书笔记 Redis中的对象——《Redis设计与实现》读书笔记 ...

klay的博客 150

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

美团二面: Redis 5 种基础数据结构?

String是Redis中最简单同时也是最常用的一个数据结构。String是一种二进制安全的数据结构,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的base64编码或者解码或者图片的路径)、序列化后的对象。虽然Redis是用C语言写的,但是Redis并没有使用C的字符串表示,而是自己构建了一种简单动态字符串SDS)。Redis中的List其实就是链表数据结构的实现。我在线性数据结构LinkedList双向链表HashMapHashSet。和。...

uuqaz的博客 650

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Redis的数据结构与对象

Redis的数据结构与对象,包括简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表、对象。

weixin_45682305的博客 869

Redis常见的数据结构与对象

该文章是作者学习了《Redis设计与实现》这本书所做的笔记,内容主要是Redis底层实现的各种数据机构和对象的细节,源码级的内容。

weixin_46322148的博客 1282

redis的数据结构与对象

SDS(Simple Dynamic String)是一种由Redis引入的字符串数据结构,旨在提高字符串处理的效率和灵活性。与C语言中的传统字符串(C字符串)相比,SDS提供了一些额外的功能和改进,特别是在内存管理和性能方面。SDS通过引入长度存储、动态扩展、空间预分配和惰性空间释放等机制,在处理字符串操作时比传统的C字符串更加高效和安全。同时,SDS的二进制安全特性和兼容部分C字符串函数的设计,使其成为一种灵活且功能强大的字符串数据结构。在Redis中,SDS的应用极大地提高了系统的性能和可靠性。双向。

z3551906947的博客 957

一位材料专业研究生的Java转型复盘

一、自我介绍先来个自我介绍吧,本硕都是材料专业,还依稀记得当初考研就是为了有个更好的平台,以后想要读博的,可当自己进入研究生阶段后,发现事实却并非像自己想象的那种剧情发展...

a934079371的博客 1298

Redis 设计与实现重点回顾

文章目录Redis 设计与实现重点回顾第一部分:数据结构与对象简单动态字符串链表字典跳跃表整数集合压缩列表对象第二部分:单机数据库的实现数据库RDB 持久化AOF 持久化事件客户端服务器第三部分:多机数据库的实现复制哨兵 Sentinel集群 Redis 设计与实现重点回顾 注:本文是《Redis 设计与实现》章节后的重点回顾,夹杂着一些个人理解 第一部分:数据结构与对象 简单动态字符串 Redis 只会使用 C 字符串作为字面量, 在大多数情况下, Redis 使用 SDS (Simple Dyn

m0_51380306的博客 394

【读书笔记】-《Redis设计与实现》数据结构与对象

文章目录【读书笔记】-《Redis设计与实现》数据结构与对象(一)1.简单动态字符串1.1 SDS的定义1.2 SDS与C字符串的区别1.2.1 常数复杂度获取字符串长度1.2.2 杜绝缓冲区溢出1.2.3 减少修改字符串时带来的内存重分配次数1.2.4 二进制安全1.2.5 兼容部分C字符串函数1.2.6 总结1.3 重点回顾2.链表2.1 链表和链表节点的实现2.2 重点回顾3.字典3.1 字典的实现3.1.1 哈希表3.1.2 哈希表节点3.1.3 字典3.2 哈希算法3.3 解决键冲突3.4 reh

小皮皮LL的博客 897

Redis之五大数据结构

Redis 共有 5 种基本数据结构:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)这 5 种数据结构是直接提供给用户使用的,是数据的保存形式,其底层实现主要依赖这 8 种数据结构:简单动态字符串(SDS)、LinkedList(双向链表)、Hash Table(哈希表)、SkipList(跳跃表)、Intset(整数集合)、ZipList(压缩列表)、QuickList(快速列表)。本章详细介绍Redis五种数据结构。

Linux运维老纪的博客 1264

Redis数据结构 对象

目录 简介 对象的类型与编码 类型 编码和底层实现 字符串对象 字符串编码的转换 字符串命令的实现 列表对象 列表编码转换 列表命令的实现 哈希对象 哈希编码转换 哈希命令的实现 集合对象 集合编码的转换 集合命令的实现 有序集合对象 有序集合编码的转换 有序集合命令的实现 类型检查与命令多态 类型检查的实现 多态命令的实现 内存回收 对象共享 对...

今天吃了吗的博客 299

【后端那些事儿】Redis设计与实现(二)对象,耐心看完你比Redis还懂Redis!

后端那些事儿

刘循源的博客 1163

《Redis开发与运维》各章重点回顾

第 1 章 初识 Redis Redis 8个特性:速度快、基于键值对的数据结构服务器、功能丰富、简单稳定、客户端语言多、持久化、主从复制、支持高可用和分布式。 Redis 不是万金油,有些场景不适合 Redis 进行开发。 开发运维解合以及阅读源码是用好 Redis 的重要方法。 生产环境中使用配置文件启动 Redis。 生产环境选取稳定版本的 Redis。 Redis 3.0 是重要的里程碑,发布了 Redis 官方的分布式实现 Redis Cluster。 第 2 章 API 的理解和使用 Re

管先森的博客 319
上一篇: Java十年功力还是涨不了薪,推荐必看《Java核心技术及面试指南》
下一篇: 离开外包之后,花了10000小时,最后我走进字节跳动拿到了offer
Java_LingFeng
博客等级 码龄4年 505粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值