Redis --- 第四讲 --- 常用数据结构 --- string类型

一、认识数据类型和编码方式

有序集合,相当于除了存储member之外,还需要存储一个score(权重,分数)

Redis底层在实现上述数据结构的时候,会在源码层面,针对上述实现进行特定的优化,来达到节省时间/节省空间的效果。特定的优化:内部具体实现的数据结构(编码方式),会有一定的变数。redis承诺,现在我这里有个hash表,你进行查询,插入,删除,操作都保证是O(1)。但是这个背后的实现,不一定就是一个标准的hash表。可能在特定场景下,使用别的数据结构实现,但是仍然保证时间复杂度符合承诺。

数据结构:redis承诺给你的,也可以理解成数据类型。

编码方式:redis内部底层的实现。

同一个数据类型,背后可能的编码实现方式是不同的,会根据特定场景进行优化。

raw:最基本的字符串。底层就是持有一个char数组,或者byte数组。

int:redis通常可以用来实现一些技术这样的功能。当value就是一个整数的时候,此时可能redis会使用int来保存。

embstr:针对短字符串进行的特殊优化。redis会自动适应,程序员在使用redis的时候没有感觉

hashtable:最基本的哈希表。redis内部的哈希表的实现。虽然和java实现方式可能不太一样,但是整体思想适合之前学过的一致的。

ziplist:压缩链表。在哈希表里面元素比较少的时候,可能优化成ziplist了。压缩列表,能够节省空间。为啥要压缩?redis上有很多的key,可能是某些key的value是hash,此时,如果key特别多,对应的hash也特别多,但是每个hash又不大的情况下,就尽量去压缩,压缩之后就可以让整体占用的内存更小了。

linkedlist:链表,元素个数多使用链表的结构实现。从redis3.2开始,引入了新的实现方式quicklist,同时兼顾了linkedlist和ziplist的优点。quicklist就是一个链表,每个元素又是一个ziplist,把空间和效率都折中兼顾到。quicklist比较类似于C++中的std::deque。

intset:集合中存的都是整数 

skiplist:链表笔试题,有一个经典的题目,复杂链表的复制。跳表也是链表,不同于普通的链表,每个节点有多个指针域,巧妙的搭配这些指针域的指向,就可以做到,从跳表上查询元素的时间复杂度为O(logN)。

使用object encoding 查看key的value的实际的编码方式。redis会自动根据当前的实际情况选择内部的编码方式,自动适应的。我们记住思想就可以了。

二、redis的单线程模型

redis只使用一个线程,处理所有的命令请求,不是说一个redis服务器进程内部真的就只有一个线程,其实也有多个线程,多个线程是在处理网络IO。假设,有多个客户端,同时操作一个redis服务器:

在上面的场景中,两个线程尝试对一个变量进行自增操作表面上看是自增两次,实际上可能只自增了一次。

当前这两个客户端,也相当于并发的发起了上述的请求,幸运的是并不会发生线程安全问题,redis服务器实际上是单线程模型,保证了当前收到的多个请求是串行执行的!多个请求同时到达redis服务器,也是要先在队列中排队,再等待redis服务器一个一个的取出里面的命令再执行。微观上讲,redis服务器是串行/顺序执行多个命令的。所以不会生成线程安全问题。

redis能够使用单线程模型,很好的工作原因主要在于redis的核心业务逻辑都是短平快的,不太消耗cpu资源也就不太吃多核了。

有很多的弊端:redis必须要特别小心,某个操作占用时间长,就会阻塞其他命令的执行!

redis虽然是单线程模型,为啥效率这么高,速度这么快呢?【重要的面试题】

参照物是数据库。

1、redis访问内存,数据库访问硬盘。

2、redis核心功能,比数据库的核心功能更简单。数据库对于数据的插入删除查询,都有更复杂的支持,这样的功能势必要花费更多的开销。redis干的活少,提供的功能相比于mysql也是少了不少。

3、单线程模型:避免了一些不必要的线程竞争开销。redis每个基本操作,都是短平快的就是简单操作一下内存数据,不是什么特别消耗cpu的操作。就算搞多个线程,提升不大。

4、处理网络IO的时候,使用了epoll这样的IO多路复用机制。一个线程,就可以管理多个socket,针对TCP来说,服务器这边每次要服务一个客户端,都需要给这个客户端安排一个socket,一个服务器服务多个客户端,同时就有很多个socket,这些socket上都是无时不刻的都在传输数据吗?很多情况下,每个客户端和服务器之间的通信也没那么频繁。此时这么多socket大部分事件都是静默的。上面是没有数据需要传输的。所以,同一时刻只有少数socket是活跃的。 

以下谈到的数据结构类型都是谈value的类型的

三、Redis中的string

Redis中的字符串,直接就是按照二进制数据的方式存储的。不会做任何的编码转换,存的是啥,取出来还是啥。讲mysql的时候,知道mysql默认的字符集,是拉丁文。插入中文就会失败,Redis就没有这种机制,存的啥就是啥。一般来说,redis遇到乱码问题的概率更小。不仅仅可以存储文本数据,整数,普通的文本字符串,JSON,xml,二进制数据(图片,视频,音频……)。音频视频体积可能会比较大,Redis对于strin类型,限制了大小最大是512M,Redis是单线程模型,希望进行的操作都能比较快速。

string类型的命令学习:

set:

set key value ex 10 表示 set key value, expire key 10。执行一个命令的原子性很强。

NX 如果key不存在,才设置,如果key存在,则不设置返回nil

XX如果key存在才设置相当于更新key的value。如果key不存在,则不设置返回nil

redis文档给出的语法格式说明

[ ]相当于一个独立的单元,表示可选项(可有可无的),其中 | 表示或者的意思,多个只能出现一个。[ ]和[ ]之间是可以同时存在的

也提供了一些命令来设置NX或者XX

SETNX

SETEX

SETPX

如果key不存在,创建新的键值对。如果key存在,则是让新的value覆盖旧的value,可能会改变原来的数据类型。原来这个key的ttl(生存时间)也会失效。

一个快速失去年终奖的技巧,清楚redis上所有的数据-删库 =》mysql里的drop database。

FLUSHALL可以把reids上所有的键值对都删除。以后在公司这是一个非常危险的命令,你少个几千甚至几万块钱你应该是不愿意的。当然不排除一些富二代。但是你不难受,公司就难受了。

get:和通用命令的get相同。对于GET来说,只是支持,字符串类型的value如果value是其他类型,使用GET获取就会出错!

MSET和MGET 一次操作多组键值对

事件复杂度为O(N),此处的N不是整个redis服务器中所有key的数量,而只是当前命令中给出的key的数量。

虽然可以一次操作多组键值对,但是不能设置太多,有可能把redis给阻塞住了。

SETNX:不存在才能设置,存在则返回失败

SETEX:指定一个key的生存时间,单位second

PSETEX:和上一个一样,但是单位是毫秒

针对set的一些常见用法,进行了缩写。之所以这样设计,就是为了让操作更符合人的直觉(使用者的门槛就越低,要背的东西就越少)。符合人的直觉,编程语言中,很多的关键字,都是和自然语言相关的。后续我们去设计一些库,设计一些工具,代码给别人使用的时候,也要尽量符合直觉,不要设计反人类,反直觉。

INCR 针对value + 1  语法:INCR key。此时key对应的value必得是整数,此操作的返回值,就是+1之后的值。incr操作的key如果不存在,就会把这个key的value当做0来使用。以下命令都是这样的操作。

INCRBY 针对value + n 加负数也是可以的。

DECR 针对value -1 返回值也是计算后的值。

DECRBY 针对value - n

INCRBYFLOAT 针对value +/-小数 ,把key对应的饿value进行+ -运算,运算的操作数可以是浮点数,虽然此处没有提供减法版本的命令,但是使用redis进行的计数操作,一般都是针对整数来进行的。

上述操作的时间复杂度都是O(1)的。由于redis处理命令的时候,是单线程模型,多个客户端同时针对同一个key进行incr操作,不会引起 "线程安全" 问题。

字符串也支持一些常用的操作,拼接,获取/修改字符串的部分内容,获取字符串长度。

append 如果key已经存在并且是一个string,命令会将value追加到原有string的后边

append返回值,长度的单位是字节!redis的字符串不会对字符编码做任何处理,当前xshell终端,默认的字符变编码是utf8,在终端中输入汉字之后,也就是按照utf8编码的,一个汉字再utf8字符集中,通常是3个字节的。

在启动redis客户端的时候,加上--raw这样的选项。就可以使redis客户端能够自动的把二进制数据尝试翻译。

getrange  获取子串  是一个闭区间。C++和JAVA中,谈到一个区间,大多都是前闭后开。 正常下标都是从0开始的整数,redis的下标使可以支持负数的。-1倒数第一个元素。

setrange 切出的字串进行修改 offset偏移量,从第几个字节开始进行替换。替换多长看实际value的长度。返回值是替换之后,新的字符串的长度。如果当前咱们value是一个中文字符串,进行setrange的时候,是可能有问题的。会导致编码失败。针对不存在的key凭空生成了一个字节,这个字节里的内容就是0x00,aaa就被追加到0x00后面了。setrange针对不存在的key也是可以操作的,不过会把offset之前的内容填充成0x00。

strlen 获取到字符串的长度,单位是字节。C++中,字符串的长度本身就是用字节为单位,java中字符串的长度则是以字符为单位的,MySQL中varchar(char)此处N的单位就是字符,MySQL中的字符,也是完整的汉字,这样的一个字符,也可能是多个字节。

,当key的value不是string时会报错。

string命令总结

string的编码方式

int :8个字节的长整型

embstr :小于等于39个字节的字符串

raw:大于39个字节的字符串

通过object encoding key查看编码格式。不建议大家去记,长度大于39这样的数字。某个业务场景,有很多的key,类型都是string,但是每个value的string长度都是100左右,更关注于整体的内存空间,因此这样的字符串使用embstr来存储也不是不能考虑,上述效果具体怎么实现?

1、先看redis是否提供了对应的配置项,可以修改39这个数字。

2、如果没有提供配置型,就需要针对redis源码进行魔改。

reids存储小数,本质上还是当作字符串来存储,这就和整数相比差别很大了,整数直接使用int来存。小数则是使用字符串来存,意味着每次进行算数运算,都需要把字符串转换成小数,进行运算,结果再转会字符串进行保存。

string的应用场景

缓存功能

整体的思路:应用服务器访问数据的时候,先查询Redis,如果Redis上数据存在了,就直接从Redis取数据交给应用服务器,不继续访问数据库了。如果Redis上数据不存在,再读取MySQL把读到的结果,返回给应用服务器,同时,把这个数据也写入到Redis中。Redis这样的缓存,经常用来存储热点数据,高频被使用的数据,这个定义方式,结合业务场景时有很多种方式。刚才上述描述的过程,相当于是把最近使用到的数据作为热点数据。暗含了一层假设,某个数据一旦被用到了,那么很可能在最近这段时间就会被反复用到。

上述策略存在一个明显的问题:

随着时间的推移,肯定会有越来越多的key在redis上访问不到,从而从mysql中读取写入redis了。此时redis中的数据会越来越多。针对这种情况我们会有一定的解决方法。

1)把数据写给redis的同时,给这个key设置一个过期时间。

2)Redis也在内存不足的时候,提供了淘汰策略。详细内容后面再说。

所以我们不用太担心上述的问题。

计数(Counter)功能

企业为啥乐意收集用户的数据?

统计 =》 进一步明确用户的需求=》根据需求改进和迭代产品。Redis并不擅长数据统计。比如想在上述的Redis中,统计,播放量前100的视频有哪个 --- 基于Redis搞就很麻烦。相比之下,如果是mysql来存储上述数据,一个sql就搞定了。

异步方式:这里写入统计数据仓库的步骤。异步的,不是说,来一个播放请求,这里就必须立即马上写一个数据。

 实际中要开发一个成熟、稳定的真实计数系统,要面临的挑战远不止如此简单:防作弊,按照不同维度计数,避免单点问题,数据持久化到底层数据源等。

共享会话

Session会话

Cookie浏览器存储数据的机制,Session服务器这边存储数据的机制,都是键值对的形式出现的。

如果每个应用服务器,维护自己的会话数据,此时彼此之间不共享。用户请求访问到不同的服务器上,就可能会出现一些不能正确处理的情况。

此时所有的会话数据,都被各个服务器共享了。

短信验证码:

手机验证码:

1、生成验证码,用户输入以下手机号,点击获取验证码,限制1分钟之内,最多获取5次验证码。用户每次获取验证码必须间隔30秒

2、检查验证码。把短信收到的验证码这一串数,提交到系统中,系统进行验证,验证码是否正确。

像发送短信这样的操作,都是由专门的SDN来实现的(第三方平台来提供服务的),但是需要充值使用。

业务是什么?

业务其实就是一个公司/一个产品,是如何解决一个/一系列问题的。解决问题的过程就成为是业务。一个公司/产品要想生存,就得赚钱,要想赚钱,就得能帮别人解决问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3 机器学习之假设空间

归纳(induction)与演绎(deduction)是科学推理的两大基本手段。前者是从特殊到一般的“泛化”(generalization)过程,即从具体的事实归结出一般性规律;后者则是从一般到特殊的“特化”(specialization)过程,即从基础原理推演出具体状况。例如&a…

学习JAVA中的Spring MVC常用注解及三层架构,这一篇就够了

Spring Web MVC 一:什么是 Spring Web MVC?什么是Servlet呢?什么是Servlet API1.1 MVC 定义1.2 什么是Spring MVC ?1.3SpringBoot和SpringMVC的区别 二:Spring MVC中常用注解的使用2.1 RequestMapping:地址映射2.2 RequestBody:请…

Golang | Leetcode Golang题解之第476题数字的补数

题目&#xff1a; 题解&#xff1a; func findComplement(num int) int {highBit : 0for i : 1; i < 30; i {if num < 1<<i {break}highBit i}mask : 1<<(highBit1) - 1return num ^ mask }

大模型缺的脑子,终于在智能体上长好了

智能体是一种通用问题解决器&#xff0c;从软件工程的角度看来&#xff0c;智能体是一种基于大语言模型的&#xff0c;具备规划思考能力、记忆能力、使用工具函数的能力&#xff0c;能自主完成给定任务的计算机程序。 大模型拥有接受输入&#xff0c;分析推理&#xff0c;继而…

k8s备份恢复(velero)

velero简介 velero官网&#xff1a; https://velero.io/ velero-github&#xff1a; https://github.com/vmware-tanzu/velero velero的特性 备份可以按集群资源的子集&#xff0c;按命名空间、资源类型标签选择器进行过滤&#xff0c;从而为备份和恢复的内容提供高度的灵活…

【Linux】【Jenkins】后端maven项目打包教程-Linux版

本次安装版本&#xff1a;2.4 jenkins详细安装教程1、安装git环境2、安装mavne环境2.1 下载依赖2.2、解压、赋权2.2、配置环境变量2.3、验证安装 3、jenkins-插件下载3.1、进入jenkins-->系统管理3.2、进入系统管理-->插件管理3.3、下载两个插件&#xff08;如果之前下载…

创建GitHub仓库和Git更换远程仓库

文章为个人笔记&#xff0c;详情请看reference 创建 GitHub 创建好账号点击自己头像&#xff0c;出现下拉菜单&#xff0c;点击Your profile 创建成功如下 下载Git 绑定用户 设置ssh-key ssh-keygen -t rsa -C “xxxxxx163.com 之后一直en回车 C:\Users\Y\ .ssh id_rsa…

数据不裸奔:如何确保AI分析顾客数据时的隐私保护

在这个信息爆炸的时代&#xff0c;数据已成为最宝贵的资源之一。人工智能&#xff08;AI&#xff09;技术的发展&#xff0c;使得我们能够从海量数据中提取有价值的信息&#xff0c;为商业决策提供支持。然而&#xff0c;随着AI在数据分析领域的广泛应用&#xff0c;顾客隐私保…

Leetcode 1857. 有向图中最大颜色值

1.题目基本信息 1.1.题目描述 给你一个 有向图 &#xff0c;它含有 n 个节点和 m 条边。节点编号从 0 到 n – 1 。 给你一个字符串 colors &#xff0c;其中 colors[i] 是小写英文字母&#xff0c;表示图中第 i 个节点的 颜色 &#xff08;下标从 0 开始&#xff09;。同时…

免费版视频压缩软件:让视频处理更便捷

现在不少人已经习惯通过视频来记录生活、传播信息和进行娱乐的重要方式。但是由于设备大家现在录制的文件都会比较大&#xff0c;这时候就比较需要一些缩小视频的工具了。今天我们一起来探讨视频压缩软件免费版来为我们带来的生动世界。 1.Foxit视频压缩大师 链接直达&#x…

《深度学习》【项目】自然语言处理——情感分析 <上>

目录 一、项目介绍 1、项目任务 2、评论信息内容 3、待思考问题 1&#xff09;目标 2&#xff09;输入字词格式 3&#xff09;每一次传入的词/字的个数是否就是评论的长度 4&#xff09;一条评论如果超过32个词/字怎么处理&#xff1f; 5&#xff09;一条评论如果…

[每周一更]-(第119期):“BP”大揭秘:生物学与金融学中的微小单位竟有如此大不同!

最近&#xff08;2024.09.29&#xff09;央行要把存量房贷在LPR&#xff08;贷款市场报价利率&#xff09;基础上&#xff0c;降低30BP&#xff0c;刚好基因行业内&#xff0c;也有bp的概念&#xff0c;通过发音无法区分&#xff0c;以下就讲解下生物学的bp和金融学的BP的概念的…

【汇编语言】寄存器(内存访问)(三)—— 字的传送

文章目录 前言1. 字的传送2. 问题一3. 问题一的分析与解答4. 问题二5. 问题二的分析与解答结语 前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但仅仅从课程的角度出发就太片面了&#xff0c;其实学习汇编语言…

Linuxtop命令查看CPU、内存使用率、解释

1. top 命令 top 是最常用的实时监控工具之一&#xff0c;可以显示 CPU 的总利用率以及各个进程的 CPU 使用情况。在Linux命令行直接输入top即可查看动态原始数据 top 在 top 命令的输出中&#xff0c;最上面的一行会显示 CPU 的使用情况&#xff1a; us&#xff08;User&a…

day01-Qt5入门

day01-Qt5入门 1.下载Qtcreate 官网地址&#xff1a;http://qt-project.org/downloads 2.配置环境变量 将类似于 D:\Qt\Qt5.1.1\5.1.1\mingw48_32\bin 的目录添加到环境变量中 3.创建一个新项目 输入自己的项目名称&#xff0c;后面默认下一部 4.运行第一个项目 在窗口…

CentOS 7 yum失效的解决办法

文章目录 一、CentOS 7停止维护导致yum失效的解决办法解决方案 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、CentOS 7停止维护导致yum失效的解决办法 020 年&#xff0c;CentOS 项目与红帽联合宣布将全部投资转向 CentOS Stream&#xff0c;这是…

Windows环境apache控制台命令行启动、停止、重启httpd服务

Windows环境apache控制台命令行启动、停止、重启httpd服务 启动&#xff1a;httpd -k start 重启&#xff1a;httpd -k restart 停止&#xff1a;httpd -k stop 需指定服务的名称&#xff1a;后面各自加上 -n 服务名 例如&#xff1a;启动指定服务的名称 httpd -k start -n 服务…

LDR6500协议芯片:诱骗取电协议,OTG数据同时实现功能芯片

在当前的电子设备市场中&#xff0c;随着USB Type-C接口的广泛应用&#xff0c;用户对充电和数据传输的需求日益提升。为了满足这一需求&#xff0c;乐得瑞科技凭借其深厚的技术积累和创新能力&#xff0c;推出了LDR6500——一款专为USB Type-C Bridge设备设计的USB PD&#xf…

CVE-2024-30269 DataEase配置信息泄露

文章目录 免责声明漏洞描述fofa影响版本漏洞复现nuclei修复建议 免责声明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 DataEase是一个开源的数据可视化分析工具&#xff0c;可以连接…

IPv6 DNS简介

IPv6网络中的每台主机都是由IPv6地址来标识的&#xff0c;用户只有获得待访问主机的IPv6地址&#xff0c;才能够成功实现访问操作。对于用户来讲&#xff0c;记住主机的IPv6地址是相当困难的&#xff0c;因此设计了一种字符串形式的主机命名机制&#xff0c;这就是域名系统。用…