文章目录

一、前言

五种基本类型:String、Hash、Set、List、Zset

对于Redis每一种数据类型,分析维度包括

1、概要介绍
2、操作命令
3、底层原理/存储结构
4、应用场景

二、String 字符串

2.1 String概要介绍

String-存储类型分为三种
1、INT 整型
2、Float 单精度浮点型
3、String 字符串

2.2 String操作命令

0 1
strlen qingshan
append qingshan good
setnx qingshan pyy
mset qingshan 2673 huihui 666
mget qingshan huihui
incr qingshan
incrby qingshan 100
decr qingshan
decrby qingshan 100
set mf 2.6
incrbyfloat mf 7.3

Redis_02_Redis五种基本类型_字符串

2.3 String底层原理

2.3.1 String在RedisObject里面是通过SDS存储的

2.3.1.1 String在RedisObject里面是通过SDS存储的

dicEntry 包括 SDS(key) 和 redisObject(value) 两个,还有一个next指针

这里的 key 是 hello ,value 是 world,我们所说的redis五种基本类型,指的是redis的value有五种基本类型,redis的key永远只有一种类型,就是String

Redis_02_Redis五种基本类型_缓存_02

RedisObject

查看一下这个RedisObject,看一下这个 value 值 “world” 是通过 SDS 存储的,如下:

Redis_02_Redis五种基本类型_缓存_03

2.3.1.2 SDS定义

SDS全称Simple Dynamic String,就是String字符串的意思。

sdshdr5: 2^5=32byte(不用)
sdshdr8: 2^8=256byte
sdshdr16:2^16=65536byte=64KB
sdshdr32:2^32byte=4GB

2.3.1.3 为什么Redis要用SDS实现字符串

为什么Redis要用SDS实现字符串?
1、内存空间预先分配
2、获取字符长度的时间复杂度O(n)
3、长度变更引起内存重新分配
4、用’\0’判断字符串结束

Redis_02_Redis五种基本类型_应用场景_04

2.3.2 Redis中String类型的三种编码

2.3.2.1 Redis中String类型的三种编码

Redis的第一种类型String,有三种编码

1、int,存储8个字节的长整型(long,2^63-1)
2、embstr,embstr格式的SDS,存储小于44个字节的字符串
3、raw,SDS,存储大于44个字节的字符串

set number 1
set huihui yes
set qs "cengjingnianshaoaizhuimengyixinzhixiangwangqianfei"
type numbser
type huihui
type

Redis_02_Redis五种基本类型_redis_05

2.3.2.2 embstr和raw的区别

embstr的只分配一次内存空间:embstr编码方式中,RedisObject和SDS在内存中连续存储的;

raw 需要分配两次内存空间:raw编码方式中,RedisObject和SDS在内存中连续存储的。

Redis_02_Redis五种基本类型_字符串_06

2.3.2.3 int和embstr什么时候转化为raw

1、int 数据不再是整数——raw
2、int大小超过了 long 的范围(2^63-1)——embstr
3、embstr长度超过了44个字节——raw

小结:string value三种编码方式,数字类型使用int,字符串使用embstr,大字符串使用raw,两者的区别是:embstr编码方式中,RedisObject和SDS在内存中连续存储的;raw编码方式中,RedisObject和SDS在内存中连续存储的。三种编码还有一个编码方式自动转换,向java上面的向上转型一样:如果数字类型从整数变为浮点数,则从 int 变为raw;如果数字类型超过 long 的范围,则从 int 变为 embstr;如果字符串长度超过 长度超过了44个字节,则从 embstr 变为 raw 。

2.3.2.4 什么时候转化?会还原吗?

1、编码转换在 Redis 写入数据时完成;
2、转换过程不可逆,只能从小内存编向大内存编转换(不包括重新set/重新给key设置值)

2.4 String应用场景

2.4.1 String应用场景

1、缓存 (可以直接使用String类型的value)
2、分布式Session (可以直接使用String类型的value)
3、分布式锁 set NX EX (可以直接使用String类型的value)
4、分布式全局ID incr (可以直接使用String类型的value)
5、计数器 incr (可以直接使用String类型的value)
6、限流 incr (可以直接使用String类型的value)
7、位操作 (可以直接使用String类型的value)

2.4.2 一个KV怎么存储一张表的数据

这是一张表的数据,如下:

id

sno

sname

company

1

GP666

mike

jingdong

2

GP777

bob

baidu

3

GP888

mary

alibaba

使用 mset 的方式,一个key就可以存放一个表记录,如下:

Redis Mset 命令用于同时设置一个或多个 key-value 对。redis Mset 命令基本语法如下:

MSET key1 value1 key2 value2 ..
redis 127.0.0.1:6379> MSET key1 "Hello" key2 "World"
OK
redis 127.0.0.1:6379> GET key1
"Hello"
redis 127.0.0.1:6379> GET key2
"World"

Redis_02_Redis五种基本类型_数据库_07

mset student:1:sno GP666 student:1:sname mike student:1:company jingdong
mget student:1:sno student:1:sname student:1:company

mset student:2:sno GP777 student:2:sname bob student:2:company baidu
mget student:2:sno student:2:sname student:2:company

mset student:3:sno GP888 student:3:sname mary student:3:company alibaba
mget student:3:sno student:3:sname student:3:company

Redis_02_Redis五种基本类型_应用场景_08

三、Hash 哈希

3.1 Hash概要介绍

存储多个无序的键值对,最大存储数量2^32-1(40亿左右)。

Redis_02_Redis五种基本类型_应用场景_09

五种基本类型是指对value的五种基本类型,key永远只有一种类型,就是String

String与Hash的区别 Hash特点:
1、节省内存空间
2、减少key冲突
3、取值减少性能消耗

Hash不适合的场景:
1、Field不能单独设置过期时间
2、需要考虑数据量分布的问题

3.2 Hash操作命令

Hash基本操作

hset h1 f 6 
hmset h1 a 1 b 2 c 3 d 4

在之前的命令前面加一个h:
set变为hset
get变为hget
mset 变成 hmset
mget 变成 hmget
就是对 hash value 的操作了

Redis_02_Redis五种基本类型_字符串_10

3.3 Hash底层原理

Hash-存储结构包含两种 ziplist 和 hashtable:
ziplist:OBJ_ENCODING_ZIPLIST(压缩列表)
hashtable:OBJ_ENCODING_HT(哈希表)

3.3.1 ziplist结构

ziplist结构
ziplist是一个经过特殊编的,由连续内存块组成的双向链表。它不存储指向一个链表节点和指向下一个链表节点的指针,而是存储一个节点长度和当前节点长度。

ziplist结构

Redis_02_Redis五种基本类型_数据库_11

ziplist

Redis_02_Redis五种基本类型_redis_12

Hash-什么时候用ziplist?
1、一个hash对象保存的field数量<512个
2、一个hash对象中所有的field和value的字符串长度都<64byte

3.3.2 HashTable结构

HashTable(dict)

1、dictEntry

2、dictht

3、dict

Redis_02_Redis五种基本类型_缓存_13

hashtable-dict存储结构

Redis_02_Redis五种基本类型_应用场景_14

3.4 Hash应用场景

Hash应用场景
String能做的,Hash都可以做;

存储对象类型的数据
key:用户id(一个用户一个购物车)
field:商品id(购物车有很多商品)
value:商品数量(每种商品数量不同)

以 购物车 为例,将购物车的数据存放到redis中,使用hash基本类型,则:
商品数量+1:hincr
商品数量-1: hincrby key field -1
删除商品:hdel
全选商品:hgetall
购物车商品种类数:hlen

四、List 列表(有序)

4.1 概要介绍

存储有序的字符串(从左到右),元素可以重复,类似 java 集合框架 List 。最大存储数量2^32-1(40亿左右)。

Redis_02_Redis五种基本类型_数据库_15

4.2 操作命令

0 
lrange queue 0

Redis_02_Redis五种基本类型_字符串_16

Redis_02_Redis五种基本类型_字符串_17

Redis Lrange 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
正数下标: 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。
负数下标:以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素

4.3 List存储原理(quicklist)

quicklist

Redis_02_Redis五种基本类型_缓存_18

quicklist
list-max-ziplist-size(fill)
正数表示单个ziplist最多所包含的entry个数。
负数代表单个ziplist的大小,默认8k。
-1:4KB;-2:8KB;-3:16KB;-4:32KB;-5:64KB

list-compress-depth(compress)
压缩深度,默认是0。
1:首尾的ziplist不压缩;
2:首尾第一第二个ziplist不压缩,以此类推

4.4 应用场景

list-应用场景
应用场景1:列表: 消息列表 文章列表 评论列表 公告列表 活动列表
应用场景2:作为队列/栈使用

五、set集合

5.1 概要介绍

Set存储String类型的无序集合,类似 java 集合框架 Set。最大存储数量2^32-1(40亿左右)。

Redis_02_Redis五种基本类型_redis_19

5.2 set-操作命令

sadd myset a b c d e f g
smembers myset
scard myset
srandmember myset
spop myset
srem myset d e f
sismember myset a

Redis_02_Redis五种基本类型_字符串_20

set集合交并差运算
set1 {a,b,c } set2 { b,c,d}
获取差集 sdiff set1 set2 {a}
获取交集(intersection ) sinter set1 set2 {b,c}
获取并集 sunion set1 set2 {a,b,c,d}

Redis_02_Redis五种基本类型_字符串_21

Redis Smembers 命令返回集合中的所有的成员。 不存在的集合 key 被视为空集合。
redis 127.0.0.1:6379> SMEMBERS key

Redis Scard 命令返回集合中元素的数量。
redis 127.0.0.1:6379> SCARD KEY_NAME

Redis Srandmember 命令用于返回集合中的一个随机元素。
从 Redis 2.6 版本开始, Srandmember 命令接受可选的 count 参数:
(1)如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
(2)如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 Srandmember 则仅仅返回随机元素,而不对集合进行任何改动。
redis 127.0.0.1:6379> SRANDMEMBER KEY [count]

Redis Spop 命令用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。
SPOP key [count]

Redis Srem 命令用于移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。
redis 127.0.0.1:6379> SREM KEY MEMBER1…MEMBERN

Redis Sismember 命令判断成员元素是否是集合的成员。
redis 127.0.0.1:6379> SISMEMBER KEY VALUE

小结:熟悉 key(String) value(Set) 命令操作
sadd key x1 添加操作 (s 表示value是set类型,add 表示添加操作,动词)
smembers key 遍历整个集合 (s 表示value是set类型,members表示所有成员)
scard key 返回整个集合member的数量 (s 表示value是set类型,card表示卡片)
srandmember key 随机返回集合中一个元素,但是不删除(s 表示value是set类型,rand表示随机,member表示成员)
spop key 随机返回集合中一个元素,但是不删除(s 表示value是set类型,pop表示弹出)
srem key xxx 指定删除member (s 表示value是set类型,rem表示 remove 删除)
sismember key x 判断key的value中是否包含x (s 表示value是set类型,is表示是否,member表示成员)

5.3 set底层原理

set-存储结构包括两种:
1、intset
2、hashtable

5.4 set-应用场景

set-应用场景
1、点赞、签到、打卡(用户记录)
2、商品标签、用户画像(人口属性、信用属性、社交、兴趣爱好…)
3、用户、推荐模型

5.4.1 点赞、签到、打卡

服务端使用like:t1001来维护t1001这条微博的所有点赞用户 (like:t1001中,like表示点赞,t1001表示微博id)
(1) 用户u3001点赞了这条微博:sadd like:t1001 u3001 (like:t1001中,添加上 u3001 用户作为成员)
(2) 用户u3001取消点赞:srem like:t1001 u3001 (like:t1001中,删去 u3001 用户这个成员)
(3) 用户u3001是否点赞:sismember like:t1001 u3001 (like:t1001中,判断 u3001 用户是否在 t1001 微博中点赞了)
(4) 点赞的所有用户:smembers like:t1001 (查询对于t1001 微博id下,点赞like的所有人数 smembers 列表)
(5) 点赞数:scard like:t1001 (查询对于t1001 微博id下,点赞like的所有人数 scard)

Redis_02_Redis五种基本类型_字符串_22

5.4.2 商品标签

用 tags:i5001来维护商品所有的标签。(tags:i5001中,tags表示标签属性,i5001表示商品id)

sadd tags:i5001 画面清晰细腻
sadd tags:i5001 真彩清晰显示屏
sadd tags:i5001 流畅至极

Redis_02_Redis五种基本类型_应用场景_23

最后效果如下图,tags表示标签属性,i5001表示商品id,最后tags:i5001中表示 i5001 这个商品id 的 商品评价

Redis_02_Redis五种基本类型_数据库_24

注意:./redis-cli --raw 启动的时候,./redis-cli 后面加上 --raw ,这样value就可以存放中文了

5.4.3 商品筛选(用set的交并补来做运算)

数据预制
sadd brand:huawei p40
sadd os:android p40
sadd screensize:6.0-6.24 p40

筛选数据(set交集):品牌华为,操作系统android,屏幕在6.0-6.24之间的
sinter brand:huawei os:android screensize:6.0-6.24

Redis_02_Redis五种基本类型_应用场景_25

Redis_02_Redis五种基本类型_redis_26

六、zset 有序集合

6.1 zset-存储结构

zset 介于 list 和 set 之间,既不允许重复(集合特性),但是又保持有序(list特性),只是zset的顺序和list的不同,list的顺序是插入顺序,zset的顺序是这个set的score分值。

zset就是给之前的 set 中的每个member加上一个score属性。

Redis_02_Redis五种基本类型_数据库_27

Redis_02_Redis五种基本类型_字符串_28

6.2 zset-操作命令

zadd myzset 10 java 20 php 30 ruby 40 cpp 50 python
zrange myzset 0 -1 withscores
zrevrange myzset 0 -1 withscores
zrangebyscore myzset 20 30
zrem myzset php cpp
zcard myzset
zrange myzset 0 -1 withscores
zmembers myzset
zincrby myzset 5 python
zcount myzset 20 60

Redis_02_Redis五种基本类型_缓存_29

Redis_02_Redis五种基本类型_缓存_30

6.3 zset-存储结构

zset-存储结构包括两种:
1、ziplist(元素数量<128,所有元素长度小于64bytes)
2、skiplist + dict

介绍一下一种新的数据结构:skiplist

skiplist:在普通的 有序链表 增加一个跳跃指针,level是随机的,增加若干这个跳跃指针是为了提高查找效率。

Redis_02_Redis五种基本类型_应用场景_31

还可以这样

Redis_02_Redis五种基本类型_数据库_32

6.4 zset-应用场景

# 排行榜
# id为6001的新闻点击数1:
zincrby hotNews:20251111 1 n6001
# 获取今天点击最多的15条:
zrevrange hotNews:20251111 0 15

Redis_02_Redis五种基本类型_缓存_33

七、尾声

Redis五种基本类型,两种图总结,如下:

Redis_02_Redis五种基本类型_缓存_34


Redis_02_Redis五种基本类型_数据库_35


Redis五种基本类型,完成了。