Redis string类型hash类型
string类型
类型介绍
在Redis中的所有的key都是string类型,而value的类型有多种。
Redis中的字符串是直接按照二进制的方式进行存储的,也就是不会做任何的编码转换,存的是什么,取出来的就是什么。这样一般来说,Redis遇见乱码的可能性会变小。因为这里会出现乱码就只跟存入端和读取端有关,而像mysql这样自己会做编码转换的,那么出现的乱码的原因还可能跟mysql自身的编码转换有关。
另外因为Redis存储字符串是按二进制存储的,所以不仅仅只可以存文本数据,
甚至还可以存图片,音频。
set/get
再看一下set的语法:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
对于后面的选项语法格式:
[expiration EX seconds|PX milliseconds] 也就是在设置key的时候,同时设置超时时间,EX就是以秒级单位的,PX就是毫秒。
[NX|XX] NX:表示 如果key存在,那么就不设置 ,返回nil;如果不存在,那么才设置。
XX:表示 key存在,才设置(相当于更新key);如果key不存在,那么就不设置。
这样的额外选项可以减少网络轮次,在客户端-服务器这样的程序下还是很有用的。 并且对于一条命令来说,它的执行效果是原子的,而分开的话就不好说了。
用命令
flushall
可以进行删库操作,将所有的数据全部删除。这个操作非常危险,几乎不会用到。
mset/mget
mset:⼀次性设置多个 key 的值。
MSET key value [key value ...]
mget:⼀次性获取多个 key 的值。如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil。
MGET key [key ...]
这里的时间复杂度官方给的是:O(N),不过这里的N跟我们之前说的一样,指的是key的数目。
这两个命令同样是为了减少请求的网络轮次的。
setnx/setex/psetex
这三个命令其实就是对set的一些常见用法进行了缩写。
incr/incrby/decr/decrby/incrbyfloat
incr只能针对一个整数使用,返回这个数加一后的值。相当于 ++i,其他的命令同理。
incrby可以针对value进行 + n的操作。并且这里的n可以是负数,如果是负数就相当于减法操作。
另外在Redis中的int是64位的。
为什么Redis明明可以使用一套命令就可以实现加减法,为什么要设计两套呢?这一点跟刚刚的setnx那些命令是一样的,是为了让Redis的使用更加符合人的直觉,从而降低用户的使用门槛。
另外,如果我们 incr/incrby的key不存在时,它会帮我们插入一个value为0的值,然后进行对应的加减操作。
剩下三个命令的使用原理跟incr和incrby差不多。这些命令的时间复杂度都是O(1)。
另外这个 incrbyfloat 中的float其实是按double的标准来的。
append
APPEND KEY VALUE
注意:append这里的返回值 的单位是字节。
如果我们想让Redis客户端能够自动的把二进制数据尝试翻译,那么在启动客户端的时候要加上一个 --raw的选项
可以看到,当我们启动时没有带 --raw时,我们查出来的汉字是十六进制显示的,其中每个十六进制前的 \x 是转义字符,表示这是一个十六进制。
getrange
GETRANGE key start end
在C++和Java中,谈到一个区间大多都是左闭右开的 [x,y) 。而Redis这里都是闭区间 [x,y]
注意:当我们存的值是汉字时,因为一个汉字占3个字节,所以使用这个切分的时候还需要考虑到这一点,不然切出来的可能是乱码
setrange
覆盖字符串的⼀部分,从指定的偏移开始。 如果从指定偏移位置覆盖的字符串超出了原本能覆盖的大小,那么多余的字符串会以追加的形式覆盖。
SETRANGE key offset value
注意:当value是一个中文字符串的时候,进行setrange是有可能出问题的。
另外,setrange对于不存在的key也是可以操作的, 不过会把 offset(偏移位置)之前的内容填充成:0x00。
strlen
获取 key 对应的 string 的⻓度。当 key 存放的类似不是 string 时,报错。
STRLEN key
string编码方式
不过不建议记住这样的数字,记住数字是没有意义的。
根据业务场景的不同,最佳的长度不一定是39字节,此时就需要自行修改这个数字的大小
关于修改:
另外,我们发现Redis存储整形会用int类型(8字节大小),但是存储小数其实是用embstr的,也就是说存储小数本质还是当作字符串来存储的。
这样的差别其实是很大的,因为对于整形 进行算术运算的时候是比较方便的,但是如果是字符串存储,那么进行算术运算的时候,要先将字符串转化为小数,然后再进行算术运算,最后还要再转回字符串,开销就大多了。
string的应用场景
作为缓存
作为缓存的思路:应用服务器访问数据时,先查询Redis,如果Redis上有这个数据,那么就直接返回给应用服务器,如果没有,那么就去MySQL中去查找,在MySQL中找到后再返回给应用服务器,同时会把这个数据写入到Redis中,这个写入到Redis中的值,作为key往往被设置了过期时间
Redis这样的缓存经常存储热点数据,也就是高频被访问的数据。这样能够加速查询和缓解MySQL服务器的压力。
伪代码模拟业务数据访问过程:
1.根据用户uid获取用户信息:
UserInfo getUserInfo(long uid) {...
}
2.⾸先从 Redis 获取⽤⼾信息,我们假设⽤⼾信息保存在 "user:info:<uid>" 对应的键中:
// 根据 uid 得到 Redis 的键
String key = "user:info:" + uid;
// 尝试从 Redis 中获取对应的值String value = Redis 执⾏命令:get key;
// 如果缓存命中(hit)
if (value != null) {// 假设我们的⽤⼾信息按照 JSON 格式存储UserInfo userInfo = JSON 反序列化(value);return userInfo;
}
3.
// 如果缓存未命中(miss)
if (value == null) {// 从数据库中,根据 uid 获取⽤⼾信息UserInfo userInfo = MySQL 执⾏ SQL:select * from user_info where uid =
<uid>// 如果表中没有 uid 对应的⽤⼾信息if (userInfo == null) {响应 404return null;}// 将⽤⼾信息序列化成 JSON 格式String value = JSON 序列化(userInfo);// 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600 秒)Redis 执⾏命令:set key value ex 3600// 返回⽤⼾信息return userInfo;
}
注意:
使⽤,可以省略业务名 "vs:"。如果键名过程,则可以使⽤团队内部都认同的缩写替代,例如
计数功能
Redis将播放量同步到其他数据源的方式是异步的。
不过Redis用作计数功能是挺不错的,但是让Redis统计数据就不行了,比如让Redis统计播放量前百的视频就很麻烦,如果让MySQL来的话一行sql就搞定了 (排序加limit 100)
共享会话
手机验证码
String 发送验证码(phoneNumber) {key = "shortMsg:limit:" + phoneNumber;// 设置过期时间为 1 分钟(60 秒)// 使⽤ NX,只在不存在 key 时才能设置成功bool r = Redis 执⾏命令:set key 1 ex 60 nxif (r == false) {// 说明之前设置过该⼿机的验证码了long c = Redis 执⾏命令:incr keyif (c > 5) {// 说明超过了⼀分钟 5 次的限制了// 限制发送return null;}}// 说明要么之前没有设置过⼿机的验证码;要么次数没有超过 5 次String validationCode = ⽣成随机的 6 位数的验证码();validationKey = "validation:" + phoneNumber;// 验证码 5 分钟(300 秒)内有效Redis 执⾏命令:set validationKey validationCode ex 300;// 返回验证码,随后通过⼿机短信发送给⽤⼾return validationCode ;
}// 验证⽤⼾输⼊的验证码是否正确bool 验证验证码(phoneNumber, validationCode) {validationKey = "validation:" + phoneNumber;String value = Redis 执⾏命令:get validationKey;if (value == null) {// 说明没有这个⼿机的验证码记录,验证失败return false;}if (value == validationCode) {return true;} else {return false;}
}

hash类型
类型介绍
基础命令 1:hset/hget/hexists/hdel
hset
设置 hash 中指定的字段(field)的值(value)。
HSET key field value [field value ...]
hget
获取 hash 中指定字段的值。
HGET key field
hexists
判断 hash 中是否有指定的字段。
HEXISTS key field
hdel
删除 hash 中指定的字段。
HDEL key field [field ...]
如果要删除所有字段,那么就是
del key
基础命令2:hkeys / hvals / hgetall
hkeys
获取 hash 中的所有字段。
HKEYS key
HVALS key
hgetall
获取 hash 中的所有字段以及对应的值。
HGETALL key
可以看到,查询出来的结果 是一对 field和value 的形式规律显示的。
上述的操作都是风险比较大的,数据量多大时就可能会导致Redis阻塞。
基础命令3:hmget / hlen / hsetnx / hincrby
hmget
⼀次获取 hash 中多个字段的值
HMGET key field [field ...]
对于hmget命令,同样也还有一个hmset命令,可以同时设置多个 filed value,但是没必要,因为hset本身就已经有这个功能了。
hlen
HLEN key
hsetnx
在字段不存在的情况下,设置 hash 中的字段和值。
HSETNX key field value
hincrby
将 hash 中字段对应的数值添加指定的值。
HINCRBY key field increment
hincrbyfloat
HINCRBYFLOAT key field increment
使用示例:
hash的编码方式
压缩的本质就是对数据进行重新编码,不同的数据有不同的特点,结合这些特点,进行精妙的设计,重新编码之后,就可以缩小体积。
示例:
哈希类型的应用场景
作为缓存
之前说过,string类型也可以作为缓存,哈希类型也可以作为缓存。
当存储结构化的数据时,使用hash作为缓存就更合适一些。
比如:
如果用string来存储这样的具有表结构的数据的话,那么就得把数据转化为json的格式。
但是如果我们只想要操作某一对filed value,那么就需要将整个key (json)读取出来,然后解析成对象,然后对其进行修改,修改完之后,又需要将字符串重新转为json,再写回去。
但是如果此时是用hash存储的数据,那么就可以很方便的取出和修改数据了。
总结:使用hash的方式确实可以高效的对filed进行读写,但是hash也付出了更大的空间上的代价
其实还有一种缓存方式,那就是用原生字符串类型。每一个属性用一个键(key)
但是这种方式是不推荐的,因为它把同一个数据的各个属性给分散开了,也就是低内聚。这里不要把内聚和耦合混淆了。
一般写代码追求的是:高内聚,低耦合。
还有一个问题就是:
缓存方式对比
string类型缓存
序列化字符串类型,例如JSON格式
哈希类型缓存
原生字符串类型
使⽤字符串类型,每个属性⼀个键。
相关文章:

Redis string类型hash类型
string类型 类型介绍 在Redis中的所有的key都是string类型,而value的类型有多种。 Redis中的字符串是直接按照二进制的方式进行存储的,也就是不会做任何的编码转换,存的是什么,取出来的就是什么。这样一般来说,Redi…...

Solidity智能合约中的异常处理(error、require 和 assert)
Solidity 中的三种抛出异常方法:error、require 和 assert 在 Solidity 开发中,异常处理是确保智能合约安全性和正确性的关键步骤。Solidity 提供了三种主要方法来抛出异常:error、require 和 assert。本文将详细介绍这三种方法的用途、实现方…...

True NAS禁用ipv6
在 TrueNAS Scale 中,禁用 IPv6 的方法如下:12 进入 System->Advanced->Sysctl,设置一个 sysctl 可调整变量 net.ipv6.conf.all.disable_ipv6,值为 1,以完全禁用 IPv6。\...

笔记整理—linux进程部分(2)使用fork创建进程
为什么要创建进程,首先每个程序的运行都需要一个进程;多进程实现宏观上的并行。 fork的原理,是进程的分裂生长模式。如果操作系统需要一个新的进程,那么就会以cp的方法得到一个新的进程,此时老的进程是父进程ÿ…...
在Python中实现多目标优化问题(6)
在Python中实现多目标优化问题 在Python中实现多目标优化,除了传统的进化算法(如NSGA-II、MOEA/D)和一些基于机器学习的方法外,还有一些新的方法和技术。这些新方法通常结合了最新的研究成果,提供了更高效的解决方案。…...

Java EE中的编码问题及解决方案
Java EE中的编码问题及解决方案 在Java EE开发中,处理字符编码是确保数据正确传输和显示的重要环节。不同的编码不一致会导致乱码,影响用户体验。本文将总结在Java EE中可能遇到的编码问题及其解决方案。 1. 输入数据编码问题 在表单提交时,…...
9月27日,每日信息差
第一、中国科学家团队在干细胞治疗领域取得重要突破,通过化学重编程技术成功制备出胰岛细胞,并用于移植治疗一名 1 型糖尿病患者,实现了临床功能性治愈。相关研究成果已发表在国际权威期刊《细胞》上。 第二、交通运输部公路局局长周荣峰在国…...
什么是 Angular 开发中的 Dumb components
Dumb components,在 Angular 开发中也被称为 Presentational components,它们的主要职责是通过展示数据和触发事件,把业务逻辑和 UI 表现分离开来。Dumb components 只通过 Input() 接收数据,Output() 向外发送事件,不…...
Docker 进入容器运行命令的详细指南
Docker 进入容器运行命令的详细指南 Docker 是一个开源的容器化平台,广泛应用于开发和生产环境中。它允许开发者打包应用程序及其依赖项到容器中,并能够在不同的平台上快速部署和运行。容器通常是独立且隔离的,但在开发、调试或维护过程中&a…...
如何禁止非真实用户的ip访问网站服务器
为了禁止非真实用户的IP访问网站服务器,可以采用多种技术手段和策略。以下是一些常用的方法: 1. 使用IP黑名单和白名单 黑名单:定期更新和维护一个IP黑名单,阻止已知的恶意IP地址或数据中心IP访问网站。白名单:对于特…...

探索SpringBoot:学科竞赛管理项目开发
2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言,在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中,Java的身影无处不在,并且拥有旺盛的生命力。Java的跨平台能力十分强大,只需一次编译,任…...

ultralytics yolo v8 示例:加载官方模型进行推理
Ultralytics YOLO 是计算机视觉和 ML 领域专业人士的高效工具。 安装 ultralytics 库: pip install ultralytics 实现代码如下: import cv2 from ultralytics import YOLO# 加载预训练的 YOLOv8n 模型 ckpt_dir "./ckpt/" # 模型缓存地址…...

【中间件学习】Nginx快速入门(为了配置一个项目)
-----------------------------本文章借鉴遇见狂神说--------------------------- 一、一个产品出现瓶颈?? 在一个产品刚刚上线的时候,并发量小,用户使用的少,所以在低并发的情况下,一个jar包启动应该就够…...

鸿蒙harmonyos next flutter通信之MethodChannel获取设备信息
本文将通过MethodChannel获取设备信息,以此来演练MethodChannel用法。 建立channel flutter代码: MethodChannel methodChannel MethodChannel("com.xmg.test"); ohos代码: private channel: MethodChannel | null nullthis.c…...

【笔记】原子结构的近代理论
近代原子结构理论的建立是从氢原子光谱得到启示的。 一、氢原子光谱与波尔理论 1.氢原子光谱 在装有两个电极的真空玻璃管内通入极少量高纯氢气,通高压电使之放电,管中发出的光束通过分光棱镜,得到分立的谱线,称为线状光谱。 发…...
【python】循环中断:break 和 continue
目录: while 循环的基础语法while 循环的基础案例while 循环的嵌套应用while 循环的嵌套案例for 循环的基础语法for 循环的嵌套应用循环中断:break 和 continue综合案例 学习目标: 掌握使用 continue 和 break 关键字控制循环 思考&#…...

WIFI密码默认显示
文章目录 需求分析遇到问题问题原因解决方案 需求 在进入设置,点击某一个wifi,连接wifi 界面,显示密码默认选中状态,效果如下 分析 在 WiFi密码被输入法挡住 中我们已经分析了整个流程,布局文件和控制中心。 结局系统设置WIFI连…...

Emiya 家今天的饭C++
题目: 样例解释: 【样例 1 解释】 由于在这个样例中,对于每组 i,j,Emiya 都最多只会做一道菜,因此我们直接通过给出烹饪方法、主要食材的编号来描述一道菜。 符合要求的方案包括: 做一道用烹饪方法 1、主要…...

Mybatis缓存机制(图文并茂!)
目录 一级缓存 需求我们在一个测试中通过ID两次查询Monster表中的信息。 二级缓存 案例分许(和上述一样的需求) EhCache第三方缓存 在了解缓存机制之前,我们要先了解什么是缓存: 缓存是一种高速存储器,用于暂时存储访问频繁的数据&…...
Git 工作区、暂存区和版本库
Git 工作区、暂存区和版本库 Git 是一个强大的版本控制系统,它帮助开发者管理代码历史,协作开发,以及跟踪和合并更改。为了更好地理解 Git 的工作流程,我们需要了解 Git 中的三个核心概念:工作区(Workspac…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...