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

news2024/12/26 2:59:48

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

有序集合,相当于除了存储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来实现的(第三方平台来提供服务的),但是需要充值使用。

业务是什么?

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

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

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

相关文章

文生图:Stable Diffusion、Midjourny

前言 Stable Diffusion(SD)和Midjourney(MJ)是当前流行的两款AI图像生成工具,它们各有特点和优势: **- Stable Diffusion是完全开源的,**这意味着用户可以免费使用,并且有技术能力…

excel如何把年龄转换为日期

总体的思路 我们从一个核心的日期函数出发 我们首先需要年月日 我的数据大概是这样的。 获取年份 第一步:提取岁前面的数字 left(目标单元格,“从左到右获取第几个字符”)第二步:替换掉数字后面的岁 第三步:新增一个单元格 在里面填入年 第四步:用…

Android系統Audio hal

一.Android系統Audio hal简介 Android系统的音频硬件抽象层(HAL)是系统与硬件之间的桥梁,允许音频应用和服务访问底层音频硬件,而无需直接与硬件交互。 主要组件: 音频 HAL 接口:定义了应用和服务如何调用音频硬件的规范。典型的音频操作包括播放、录制、音量控制等。 …

N1060A 50/85GHz精密型波形分析模块

N1060A 50/85GHz精密型波形分析模块 苏州新利通 概述 Keysight N1060A 精密型波形分析仪是一款数字通信分析仪(DCA)模块,可与 Keysight N1000A 主机兼容。 与是德科技的所有其他 DCA 模块一样,N1060A 提供了广泛的配置和性能选…

【C语言】数组函数冒泡排序bubble sort

数组:对于n个数字进行排序,就必须定义n个变量来存储。那么为了统一处理,选择数组就十分便捷了。 函数:将排序算法写到函数中,后续遇到所有的排序需求,都可以直接进行调用。 冒泡排序:受气泡在水…

HDFS详细分析

目录 一、HDFS架构 (1)Block - 数据块 (2)MetaData - 元数据 (3)NameNode - 主结点 (4)DataNode - 从结点 (5)SecondaryNameNode 二、HDFS的特点 &…

【19楼-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

2024年下软考——信息系统运行管理员考前30天冲刺学习指南!!!

2024下半年软考已经迫在眉睫了,还没有开始备考的小伙伴赶紧行动起来。为了帮助大家更好的冲刺学习,特此提供一份信息系统运行管理员考前30天学习指南。本指南包括考情分析、学习规划、冲刺攻略三个部分,可以参考此指南进行最后的复习要领&…

javaWeb项目-Springboot+vue-校园论坛系统功能介绍

本项目源码(点击下方链接下载):java-springbootvue-xx学校校园论坛信息系统实现源码(项目源码-说明文档)资源-CSDN文库 项目关键技术 开发工具:IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架:ssm、Springboot…

鼠标移入盒子,盒子跟随鼠标移动

demo效果: 鼠标移入盒子,按下鼠标,开启移动跟随移动模式,再次按下关闭移动模式 涉及主要属性 在元素上单击鼠标按钮时输出鼠标指针的坐标: var x event.pageX; // 获取水平坐标 var y event.pageY; // 获取垂直坐标元素offsetL…

【含开题报告+文档+PPT+源码】基于SSM的景行天下旅游网站的设计与实现

开题报告 随着互联网的快速发展,旅游业也逐渐进入了数字化时代。作为一个旅游目的地,云浮市意识到了互联网在促进旅游业发展方面的巨大潜力。为了更好地推广云浮的旅游资源,提高旅游服务质量,云浮市决定开发一个专门的旅游网站。…

【python】用tk做一个简单的商品搜索更新展示的桌面应用

import tkinter as tk from tkinter import ttk import pandas as pddata_list [{id:1,name: 苹果, price: 6.5,tag:水果},{id:2,name: 香蕉, price: 2.5,tag:水果},{id:3,name: 葡萄, price: 8.5,tag:水果},{id:4,name: 橘子, price: 4.5,tag:水果}, ]df pd.DataFrame(data_…

SwiftUI 如何取得 @Environment 中 @Observable 对象的绑定?

概述 从 SwiftUI 5.0(iOS 17)开始,苹果推出了全新的 Observation 框架。它作为下一代内容改变响应者全面参与到数据流和事件流的系统中。 有了 Observation 框架的加持,原本需要多种状态类型的 SwiftUI 视图现在只需要 3 种即可大…

海康NVR管理平台EasyNVR多品牌NVR管理工具实现智能化视频管理介入现代化工厂

一、方案背景 在当今这个日新月异的时代,制造业作为国民经济的支柱之一,正经历着前所未有的变革。随着信息技术的飞速发展,工厂的现代化管理手段准确性也越来越高,越来越丰富,各种先进的技术手段比如视频监控系统&…

R语言医学数据分析实践-R编程环境的搭建

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言编程_夏天又到了的博客-CSDN博客 R语言对编程环境的要求不高,可以在多种操作系统平台上…

对于SOCKS协议的一些认知误区有哪些?

代理协议在设备与代理服务器之间的数据交换中起到了关键作用。在这方面,SOCKS代理协议是常见的选择之一,被广泛应用于下载、传输和上传网络数据的场景。然而,关于SOCKS代理协议存在一些常见的误解,让我们来逐一了解。 一、使用SO…

nRF54L15—蓝牙低功耗双核系统级芯片(SoC)

nRF54L15 是 nRF54L 系列的首款系统级芯片 (SoC)。它是一款超低功耗蓝牙 5.4 SoC,具有同类最佳的新型多协议无线电和先进的安全功能。nRF54L 系列以更紧凑的封装将广受欢迎的 nRF52 系列提升到新的水平,具有出色的处理能力和效率、扩展的内存和新型外设。…

开发 - develop-codescan-zwcz53

开发 - develop-codescan-zwcz53 1. 开发 - CodeScan2. 前言3. CodeScan3.1. 工具概述3.2. 编译3.3. 功能3.4. 使用3.5. 高级用法3.5.1. 高扩展性3.5.2. 扫描位置3.5.3. 过滤字符串(只写了JSP PHP)3.5.4. 静态分析依赖情况 3.6. TODO3.7. 支持项目3.8. 详细使用文章(内附案例)…

运维怎么转行网络安全?

经常有人问我:干网工、干运维多年遇瓶颈,想学点新技术给自己涨涨“身价”,应该怎么选择? 聪明人早已经用脚投票:近年来,越来越多运维的朋友寻找新的职业发展机会,将目光聚焦到了网络安全产业。…

大数据-174 Elasticsearch Query DSL - 全文检索 full-text query 匹配、短语、多字段 详细操作

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…