Redis实战 | Redis数据5种类型详解
wptr33 2024-12-18 17:32 17 浏览
Redis是目前非常主流的KV数据库,它因高性能的读写能力而著称,其实还有另外一个优势,就是Redis提供了更加丰富的数据类型,这使得Redis有着更加广泛的使用场景。那Redis提供给用户的有哪些数据类型呢?主要有:string(字符串)、List(列表)、Set(集合)、Hash(哈希)、Zset(有序集合)、HyperLogLogs(计算基数用的一种数据结构)、Streams(Redis 5.0提供一种建模日志用的全新数据结构)。
需要注意的是这里说的数据类型是指Redis值的数据类型,而Redis键的类型总是string。
本文主要详解一下前5种,也就是最常用的5种数据类型。剩下两种可上Redis官网(redis.io)自行了解下。另外,Redis已经是目前Java程序员面试必问内容,而 “Redis有哪些数据类型?” 更是面试官张口就来的基础问题。如果连这第一问都过不了,那基本上Redis这块已经凉凉了。
string | 字符串类型
redis的字符串类型,可以存储字符串、整数或者浮点数。如果存储的是整数或者浮点数,还能执行自增或者自减操作。
并且redis的string类型是二进制安全的,它可以包含任何数据,比如一个序列化的对象、一个图片字节流等。不过存储大小是有上限的-512M
这里解释下二进制安全的含义:简单地来说,就是字符串不是根据某种特殊的标志位来(C语言的\0)解析的,无论输入的是什么,总能保证输出是处理的原始输入而不是根据某种特殊格式来处理。
redis是怎么实现string类型的二进制安全的呢?
答案是Sds (Simple Dynamic String,简单动态字符串),Redis底层定义了自己的一种数据结构。(简单了解下)
typedef char *sds;
struct sdshdr {
// buf 已占用长度
int len;
// buf 剩余可用长度
int free;
// 实际保存字符串数据的地方
char buf[];
};
操作字符串的一些命令
基础set、get、del命令及示例
get keyname 获取存储在给定键中的值
set keyname value 设置存储点给定键中的值
del keyname 删除存储在给定键中的值(通用命令,适用于所有类型)
127.0.0.1:6379> set happy today
OK
127.0.0.1:6379> get happy
"today"
127.0.0.1:6379> del happy
(integer) 1
127.0.0.1:6379> get happy
(nil)
127.0.0.1:6379>
自增和自减命令
incr keyname 将键存储的值加1
decr kename 将键存储的是减1
incrby keyname amount 将键存储的值加上整数amount
decrby keyname amount 将键存储的值减去整数amount
incrbyfloat keyname amount 将键存储的值加上浮点数amount
127.0.0.1:6379> set number 1
OK
127.0.0.1:6379> get number
"1"
127.0.0.1:6379> incr number
(integer) 2
127.0.0.1:6379> get number
"2"
127.0.0.1:6379> decr number
(integer) 1
127.0.0.1:6379> get number
"1"
127.0.0.1:6379> incrby number 3
(integer) 4
127.0.0.1:6379> get number
"4"
127.0.0.1:6379> decrby number 2
(integer) 2
127.0.0.1:6379> get number
"2"
127.0.0.1:6379> incrbyfloat number 1.23
"3.23"
127.0.0.1:6379> get number
"3.23"
子串和二进制位命令
append keyname value 追加value值到指定字符串末尾
getrange keyname start end 获取start到end范围的所有字符组成的子串,包括start和end在内
setrange keyname offset value 从偏移量 offset 开始, 用 value 参数覆写(overwrite)键 keyname 储存的字符串值。
getbit keyname offset 对 keyname 所储存的字符串值,获取指定偏移量上的位(bit)。
setbit keyname offset value 对 keyname 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
注意redis的索引以0为开始
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> append hello ,java
(integer) 10
127.0.0.1:6379> get hello
"world,java"
127.0.0.1:6379> getrange hello 2 5
"rld,"
127.0.0.1:6379> setrange hello 6 redis
(integer) 11
127.0.0.1:6379> get hello
"world,redis"
127.0.0.1:6379>
127.0.0.1:6379> setbit bitstr 100 1
(integer) 0
127.0.0.1:6379> getbit bitstr 100
(integer) 1
127.0.0.1:6379> get bitstr
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b"
127.0.0.1:6379>
其他几个重要的命令
setnx key value 只在键 key 不存在的情况下, 将键 key 的值设置为 value;若键 key 已经存在, 则 SETNX 命令不做任何动作。
setex key seconds value 将键 key 的值设置为 value , 并将键 key 的生存时间设置为 seconds 秒钟。如果键 key 已经存在, 那么 SETEX 命令将覆盖已有的值。
说明一下: - SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。命令在设置成功时返回 1 , 设置失败时返回 0 。 - SETEX命令相当于SET key value 和 EXPIRE key seconds # 设置生存时间两条命令的效果,但是SETEX是一个原子操作。
127.0.0.1:6379> exists mark
(integer) 0
127.0.0.1:6379> setnx mark abcd
(integer) 1
127.0.0.1:6379> setnx mark defg
(integer) 0
127.0.0.1:6379> get mark
"abcd"
127.0.0.1:6379> setex cachekey 20 ak98
OK
127.0.0.1:6379> get cachekey
"ak98"
127.0.0.1:6379> ttl cachekey
(integer) 2
List | 列表类型
Redis的列表类型和许多程序语言中的列表类型类似,可以有序地存储多个字符串。
支持从列表的左端和右端推入或弹出元素。Redis列表的底层实现是压缩列表(redis内容自己实现的数据结构)和双端链表。看下图
图片来自《Redis 设计与实现》
列表操作命令详解
lpush key value [value...]
将一个或者多个value值插入列表的表头。如果 key 不存在,会创建一个空列表并执行 LPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。
执行 LPUSH 命令后,会返回列表的长度。
127.0.0.1:6379> lpush listkey a
(integer) 1
127.0.0.1:6379> lpush listkey a b c
(integer) 4
127.0.0.1:6379> lrange listkey 0 -1
1) "c"
2) "b"
3) "a"
4) "a"
127.0.0.1:6379>
- list类型可以加入重复的元素,这个和后面要说的set(集合类型)不同。
- lrange listkey 0 -1 是获取整个列表的内容
- 类似的rpush命令是从列表右端加入元素
LPOP key
从列表的左端弹出一个值,并返回被弹出的值
127.0.0.1:6379> lrange listkey 0 -1
1) "c"
2) "b"
3) "a"
4) "a"
127.0.0.1:6379> lpop listkey
"c"
127.0.0.1:6379> lrange listkey 0 -1
1) "b"
2) "a"
3) "a"
127.0.0.1:6379>
lrange key start end
获取列表key在给定start到end范围上的所有元素值。
0表示第一个元素,-1表示最后一个元素。
127.0.0.1:6379> lrange listkey 0 -1
1) "b"
2) "a"
3) "a"
127.0.0.1:6379> lrange listkey 0 1
1) "b"
2) "a"
127.0.0.1:6379>
lindex key index
获取列表在给定index位置上的单个元素值。
可以是-1,代表最后一个元素,-2表示倒数第二个元素,以此类推。
127.0.0.1:6379> lrange listkey 0 -1
1) "b"
2) "a"
3) "a"
127.0.0.1:6379> lindex listkey 0
"b"
127.0.0.1:6379> lindex listkey -1
"a"
127.0.0.1:6379> lindex listkey 3
(nil)
127.0.0.1:6379>
blpop key [key …] timeout
blpop 是阻塞式的弹出命令,它是lpop key 命令的阻塞版本。当给定列表内没有任何元素可供弹出的时候,连接将被 blpop 命令阻塞,直到等待超时或发现可弹出元素为止。
当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。
因此可以分两种情况讨论,一种是至少有一个key存在且是非空列表,则blpop命令不会阻塞,另外是blpop命令中的列表是空列表,此时会在超时时间内阻塞。
先看下非阻塞的场景,返回值是第一个非空列表名和被弹出元素。
127.0.0.1:6379> lpush list1 hello java
(integer) 2
127.0.0.1:6379> lpush list2 hello redis
(integer) 2
127.0.0.1:6379> blpop list2 list1 list3 0
1) "list2"
2) "redis"
127.0.0.1:6379>
阻塞的场景,在执行了blpop book1 book2 300 命令后会一直阻塞住。
127.0.0.1:6379> exists book1
(integer) 0
127.0.0.1:6379> exists book2
(integer) 0
127.0.0.1:6379> blpop book1 book2 300
这个时候,我们如果在开另外一个redis客户端,执行如下lpush命令往book1列表中推入一个元素。
127.0.0.1:6379> lpush book1 springboot
(integer) 1
127.0.0.1:6379>
此时,再回到原来阻塞的客户端,已经弹出了元素。
127.0.0.1:6379> exists book1
(integer) 0
127.0.0.1:6379> exists book2
(integer) 0
127.0.0.1:6379> blpop book1 book2 300
1) "book1"
2) "springboot"
(237.45s)
127.0.0.1:6379>
通过利用Redis列表类型的阻塞式命令的特性,我们最容易想到的就是可以用它实现一个简易版的消息队列。
set | 集合类型
Redis的集合以无序的方式存储多个不同的元素。这里要注意的是无序和不同。
除了对集合能快速执行添加、删除、检查一个元素是否在集合中之外,还可以对多个集合执行交集、并集和差集运算。
底层实现概述
Redis的集合类型底层实现主要是通过一种叫做字典的数据结构。不过Redis为了追求极致的性能,会根据存储的值是否是整数,选择一种intset的数据结构。当满足一定条件后,会切换成字典的实现。
这里大概解释下字典: 其实是由一集键值对(key-value pairs)组成, 各个键值对的键各不相同, 程序可以添加新的键值对到字典中, 或者基于键进行查找、更新或删除等操作。
Redis的set(集合)在使用字典数据结构保存数据时,将元素保存到字典的键里面, 而字典的值则统一设为 NULL 。
集合类型操作命令详解
sadd key member [member...]
将一个或者多个元素添加到集合key中,已存在于集合中的元素将被忽略。返回新添加的元素数量,不包括忽略的元素。
srem key member [member...]
移除集合中的一个或多个元素,不存在的元素将被忽略。返回被成功移除的元素数量。
sismember key meber
检查元素member是否存在于集合key中。如果是返回1,不是或者key不存在,返回0。
scard key 返回集合包含的元素数量
spop key 随机移除集合中的一个元素,并返回被移除元素。
smembers key 返回集合中包含的所有元素
127.0.0.1:6379> sadd set1 java spring redis
(integer) 3
127.0.0.1:6379> smembers set1
1) "redis"
2) "spring"
3) "java"
127.0.0.1:6379> scard set1
(integer) 3
127.0.0.1:6379> srem set1 spring
(integer) 1
127.0.0.1:6379> sismember set1 spring
(integer) 0
127.0.0.1:6379> smembers set1
1) "redis"
2) "java"
127.0.0.1:6379> sadd set1 mysql spring
(integer) 2
127.0.0.1:6379> spop set1
"redis"
127.0.0.1:6379> smembers set1
1) "mysql"
2) "spring"
3) "java"
127.0.0.1:6379>
下面是一些用于处理多个集合的一些命令
sdiff key [key...] 返回存在于第一个集合,但不存在于其他集合中的元素(数学上的差集运算)
sinter key [key...] 返回同时存在于所有集合中的元素(数学上的交集运算) sunion key [key...] 返回至少存在于一个集合中的元素(数学上的并集运算)
127.0.0.1:6379> smembers set1
1) "mysql"
2) "spring"
3) "java"
127.0.0.1:6379> smembers set2
1) "mysql"
2) "springboot"
3) "redis"
127.0.0.1:6379> sdiff set1 set2
1) "java"
2) "spring"
127.0.0.1:6379> sinter set1 set2
1) "mysql"
127.0.0.1:6379> sunion set1 set2
1) "mysql"
2) "springboot"
3) "java"
4) "spring"
5) "redis"
127.0.0.1:6379>
hash | 散列表(哈希表)
Redis的hash类型其实就是一个缩减版的redis。它存储的是键值对,将多个键值对存储到一个redis键里面。
底层实现概述
hash类型的底层主要也是基于字典这种数据结构来实现的。
redis内部在实现hash数据类型的时候是使用了两种数据结构。在创建一个空的hash表时,默认使用的是ziplist的数据结构,满足一定条件后会转成字典的形式。
散列表操作命令详解
hmget hash-key key [key...] 从散列表里面获取一个或多个键的值
hmset hash-key key value [key value...] 为散列表里面的一个或多个键设置值 hdel hash-key key [key...] 删除散列表里面的一个或多个键值对,返回删除成功的键值对的数量
hlen hash-key 返回散列表包含的键值对的数量
hexists hash-key key 检查给定的键是否存在于散列表中
hkeys hash-key 获取散列包含的所有键
hvals hash-key 获取散列包含的所有值
hgetall hash-key 获取散列包含的所有键值对
127.0.0.1:6379> hmset hash1 username tom email 123@123 year 12
OK
127.0.0.1:6379> hmget hash1 email
1) "123@123"
127.0.0.1:6379> hlen hash1
(integer) 3
127.0.0.1:6379> hdel hash1 year
(integer) 1
127.0.0.1:6379> hexists hash1 year
(integer) 0
127.0.0.1:6379> hkeys hash1
1) "username"
2) "email"
127.0.0.1:6379> hvals hash1
1) "tom"
2) "123@123"
127.0.0.1:6379> hgetall hash1
1) "username"
2) "tom"
3) "email"
4) "123@123"
127.0.0.1:6379>
zset | 有序集合
有序集合相比较于集合,多个有序两个字,我们知道set集合类型存储的元素是无序的,那Redis有序集合是怎么保证有序的?使用分值,有序集合里存储着成员与分值之间的映射,并提供了分值处理命令,以及根据分值的大小有序地获取成员或分值的命令。
底层实现概述
Redis有序集合的实现使用了一种叫跳跃表的数据结构(简称跳表,可自行查阅),同时也使用到了前面提到的压缩列表。也是满足一定条件的话,会自行转换。
有序集合操作命令详解
zadd z-key score memer [score member...] 将带有给定分值的成员添加到有序集合里面
zrem z-key member [member...] 从有序集合里面移除给定的成员,并返回被移除成员的数量
zcard z-key 返回有序集合包含的成员数量
zincrby z-key increment member 将member成员的分值加上increment
zcount z-key min max 返回分值介于min和max之间的成员数量
zrank z-key member 返回成员member在有序集合中的排名
zscore z-key member 返回成员member的分值
zrange z-key start stop [withscores] 返回有序集合中排名介于start和stop之间的成员,如果给定了可选的withscores选项,name命令会将成员的分值也一并返回。
zrevrank z-key member 返回有序集合里成员member的排名,成员按照分值从大到小排列。
zrevrange z-key start stop 返回有序集合给定排名范围内的成员,成员按照分值从大到小排列。
zrangebyscore z-key min max 返回有序集合中分值介于min和max之间的所有成员
127.0.0.1:6379> zadd zset1 10 a 12 b 1 c 3 d 20 e
(integer) 5
127.0.0.1:6379> zcard zset1
(integer) 5
127.0.0.1:6379> zcount zset1 2 10
(integer) 2
127.0.0.1:6379> zrank zset1 d
(integer) 1
127.0.0.1:6379> zscore zset1 e
"20"
127.0.0.1:6379> zrange zset1 3 5
1) "b"
2) "e"
127.0.0.1:6379> zrevrank zset1 d
(integer) 3
127.0.0.1:6379> zrevrange zset1 3 5
1) "d"
2) "c"
127.0.0.1:6379> zrangebyscore zset1 5 10
1) "a"
127.0.0.1:6379>
相关推荐
- Python自动化脚本应用与示例(python办公自动化脚本)
-
Python是编写自动化脚本的绝佳选择,因其语法简洁、库丰富且跨平台兼容性强。以下是Python自动化脚本的常见应用场景及示例,帮助你快速上手:一、常见自动化场景文件与目录操作...
- Python文件操作常用库高级应用教程
-
本文是在前面《Python文件操作常用库使用教程》的基础上,进一步学习Python文件操作库的高级应用。一、高级文件系统监控1.1watchdog库-实时文件系统监控安装与基本使用:...
- Python办公自动化系列篇之六:文件系统与操作系统任务
-
作为高效办公自动化领域的主流编程语言,Python凭借其优雅的语法结构、完善的技术生态及成熟的第三方工具库集合,已成为企业数字化转型过程中提升运营效率的理想选择。该语言在结构化数据处理、自动化文档生成...
- 14《Python 办公自动化教程》os 模块操作文件与文件夹
-
在日常工作中,我们经常会和文件、文件夹打交道,比如将服务器上指定目录下文件进行归档,或将爬虫爬取的数据根据时间创建对应的文件夹/文件,如果这些还依靠手动来进行操作,无疑是费时费力的,这时候Pyt...
- python中os模块详解(python os.path模块)
-
os模块是Python标准库中的一个模块,它提供了与操作系统交互的方法。使用os模块可以方便地执行许多常见的系统任务,如文件和目录操作、进程管理、环境变量管理等。下面是os模块中一些常用的函数和方法:...
- 21-Python-文件操作(python文件的操作步骤)
-
在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件...
- 轻松玩转Python文件操作:移动、删除
-
哈喽,大家好,我是木头左!Python文件操作基础在处理计算机文件时,经常需要执行如移动和删除等基本操作。Python提供了一些内置的库来帮助完成这些任务,其中最常用的就是os模块和shutil模块。...
- Python 初学者练习:删除文件和文件夹
-
在本教程中,你将学习如何在Python中删除文件和文件夹。使用os.remove()函数删除文件...
- 引人遐想,用 Python 获取你想要的“某个人”摄像头照片
-
仅用来学习,希望给你们有提供到学习上的作用。1.安装库需要安装python3.5以上版本,在官网下载即可。然后安装库opencv-python,安装方式为打开终端输入命令行。...
- Python如何使用临时文件和目录(python目录下文件)
-
在某些项目中,有时候会有大量的临时数据,比如各种日志,这时候我们要做数据分析,并把最后的结果储存起来,这些大量的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件,存储这些临时数据。使用标...
- Linux 下海量文件删除方法效率对比,最慢的竟然是 rm
-
Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...
- Python 开发工程师必会的 5 个系统命令操作库
-
当我们需要编写自动化脚本、部署工具、监控程序时,熟练操作系统命令几乎是必备技能。今天就来聊聊我在实际项目中高频使用的5个系统命令操作库,这些可都是能让你效率翻倍的"瑞士军刀"。一...
- Python常用文件操作库使用详解(python文件操作选项)
-
Python生态系统提供了丰富的文件操作库,可以处理各种复杂的文件操作需求。本教程将介绍Python中最常用的文件操作库及其实际应用。一、标准库核心模块1.1os模块-操作系统接口主要功能...
- 11. 文件与IO操作(文件io和网络io)
-
本章深入探讨Go语言文件处理与IO操作的核心技术,结合高性能实践与安全规范,提供企业级解决方案。11.1文件读写11.1.1基础操作...
- Python os模块的20个应用实例(python中 import os模块用法)
-
在Python中,...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)