Redis-结构化value对象的类型
文章目录
- 一、Redis的结构化value对象类型的介绍
- 二、Redis的这些结构化value对象类型的通用操作
- 查看指定key的数据类型
- 查看所有的key
- 判断指定key是否存在
- 为已存在的key进行重命名
- 为指定key设置存活时间
- pexpire与expire
- 查看指定Key的存活时间
- 为指定key设置成永久存活
- 三、Redis中的结构化value对象类型之String类型及其操作
- String型的value典型操作之针对数字类型
- String型的value典型操作之针对字节串类型
- 设置String类型的key同时设置过期时间
- 同时设置多个String类型的数据
- 同时查看多个String类型的数据
- 查看String类型的数据的字符长度
- 查看要修改的key的原的值(输出在终端)同时修改key的值
- 将key的值递增
- 将key的值+1
- 将key的值+n
- 将key的值递减
- 将key的值-1
- 将key的值-n
- 将key的值的末尾追加内容
- 查看String类型的数据(字符串)的指定某一位到某一位的部分
- 修改String类型的数据(字符串)的指定某一位的值
- 四、Redis中结构化value对象类型之Map类型及其操作
- Hash数据结构介绍
- map的主要操作
- Redis Map(Hash)类型的实际应用例子
- 五、Redis中结构化value对象类型之List类型及其操作(操作中有栈和队列的思想)
- 针对单个key的元素的List类型的操作
- List类型的复杂的操作(方便类似生产者消费者模式场景的实现)
- *拓展:生产者消费者模式
- 核心概念
- 模式特点
- 工作流程
- 实现要点
- 示例代码(Python)
- `lpush`和`rpush`命令用于给一个List类型的对象添加数据
- `rpop`和`rpush`命令用于给一个List类型的对象删除数据
- `llen`命令用于查看一个List类型的对象有几个数据
- `lpush`推进去的数据需用`rpop`弹出、`rpush`推入的需用`lpop`弹出
- `lindex`用于查看一个List类型的对象的(从左往右数)的第一个成员的值(0表示第一个成员)
- `lrange`命令用于查看一个List类型的对象的(从左往右数) 第几个成员到第几个成员的部分
- `linsert`用于在一个List类型对象中(从左往右数)的指定成员名的前或后插入一个成员
- `rpoplpush`复合命令,用于将一个List对象(从右边)弹出一个成员然后紧接着操作另一个List对象(在左边)推入这个成员进去
- `lrem`命令用于(从左往右数)删除指定次数的成员(如果有重复名的成员的话,那么count>1如果不是那么只写1)
- `ltrim`命令用于保留List对象的(从左往右数)第几个到第几个的成员
- `lset`命令用于设置一个List对象的(从左往右数)第几个成员的值(0表示第一个成员)
- Redis List类型的实际应用例子
- 六、Redis结构化value对象类型之Set类型及其操作
- set基本操作
- Redis中的Set的实际应用场景
- 七、Redis结构化value对象类型之Sorted-Set类型及其操作
- Sorted-Sort的基本操作
- `zadd`
- `zrange`
- `revrange`
- `zrangebyscore`
- `zrank`
- `zrem`
- `zincrby`
- `zcard`
- `zscore`
- `zremrangebyrank`
- `+inf`和`-inf`以及`limit`参数
- Redis中的Sorted-Set的实际应用场景
一、Redis的结构化value对象类型的介绍
Redis常用的value包含5种类型:string、list、set、map、sorted-set
上面的value对象(数据类型的对象)在Redis内部的通用结构如下:
typedef struct redisObject{
unsigned type:4; //":4"表示占用4位
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS;
int refcount;
void *ptr;
} robj;
- type:指这些结构化类型
- encoding:指的是这些结构化类型在具体的实现(承载)方式,同一个类型可以有多种实现,例如String可以用int来承载,也可用用封装的char[]来承载,List可用ziplist或者链表来承载;
- lru:表示本对象的空转时长,用于有限内存下长久不访问的对象的清理;
- refcount:是应用技术用于对象的垃圾回收
- prt指向的就是以enconding方式实现这个对象的实际承载者的地址,例如string对象对应的sds地址(sds是一种结构)
二、Redis的这些结构化value对象类型的通用操作
查看指定key的数据类型
#进入redis-cli后
type <指定key名>
查看所有的key
# 进入redis-cli后:
keys *
判断指定key是否存在
# 进入redis-cli后
exists <指定key名>
为已存在的key进行重命名
# 进入redis-cli后
rename <已存在的原key名> <新key名>
为指定key设置存活时间
#设置以秒为单位的存活时间
expire <指定key名> <存活时间(多少秒)>
#设置以毫秒为单位的存活时间
pexpire <指定key名> <存活时间(多少毫秒)>
pexpire与expire
pexpire: pico(微小单位)expire
在Redis中,EXPIRE
和PEXPIRE
命令都用于设置键的过期时间,它们的主要区别在于过期时间的单位不同:
-
EXPIRE命令:
EXPIRE
命令用于为指定的键设置一个过期时间(单位为秒)。- 语法:
EXPIRE key seconds
- 其中
key
是要设置过期时间的键,seconds
是过期时间,以秒为单位。 - 例如,
EXPIRE mykey 60
会将键mykey
的过期时间设置为60秒。
-
PEXPIRE命令:
PEXPIRE
命令用于为指定的键设置一个过期时间(单位为毫秒)。- 语法:
PEXPIRE key milliseconds
- 其中
key
是要设置过期时间的键,milliseconds
是过期时间,以毫秒为单位。 - 例如,
PEXPIRE mykey 60000
会将键mykey
的过期时间设置为60秒(60000毫秒)。
区别:
- 时间单位:
EXPIRE
使用秒作为单位,而PEXPIRE
使用毫秒作为单位。这允许PEXPIRE
设置更精确的过期时间,特别是当需要比秒更细粒度的控制时。 - 适用场景:如果你需要以秒为单位设置过期时间,使用
EXPIRE
;如果需要以毫秒为单位设置过期时间,使用PEXPIRE
。
使用场景示例:
- 如果你有一个缓存需求,需要在3600秒后过期,可以使用
EXPIRE mykey 3600
。 - 如果你需要在3600秒加上500毫秒后过期,可以使用
PEXPIRE mykey 3600500
。
在实际应用中,选择EXPIRE
还是PEXPIRE
取决于你的具体需求和过期时间的精度要求。
查看指定Key的存活时间
永久存活,则返回-1
ttl <指定key名>
”ttl“指的是:time to live
为指定key设置成永久存活
persist <指定key名>
三、Redis中的结构化value对象类型之String类型及其操作
Redis的结构化value对象类型中的string能表达3中指的类型:
- 字节串
- 整数
- 浮点数
3中类型间根据具体场景由redis完成相互间的自动转型,并且根据需要选取底层的承载方式;
比如,下面的数字类型就可以自动转换成字节串类型,然后可以进行字节串类型的一些操作,然而字节串类型就不可轻易转换成数字类型进行数字类型的操作;
String型的value典型操作之针对数字类型
操作 | 描述 |
---|---|
incr | 将指定key内容+1 |
decr | 将指定key内容-1 |
incrby | 将指定key的内容增加给定的值 |
decrby | 将指定key的内容减少给定的值 |
incrbyfloat | 将指定key的内容减少给定的浮点值 |
String型的value典型操作之针对字节串类型
操作 | 描述 |
---|---|
append | 将指定字节串的内容添加到指定key对应的value后 |
getrange | 对字节串value做范围截取 |
setrange | 对指定字符串内容覆盖,指定key对应的value,从指定位置开始覆盖 |
strlen | 获取字节串value的长度 |
getbit | 对字节串value,获取指定偏移量上的bit |
setbit | 将字节串value视为bit串并设置从给定起始位置起设置值 |
bitcount | 将字节串value视为bit串并统计1的数量 |
bitop | 对多个key的value值做位操作,如:XOR、OR、AND、NOT |
字节串和字符串的区别:
在计算机编程中,“字节串”(byte string)和“字符串”(string)这两个术语通常用来描述不同类型的数据结构,它们的区别主要体现在数据类型、存储内容和使用场景上:
-
数据类型:
- 字符串(String):通常指的是由字符组成的序列,每个字符在计算机中通常占用固定数量的比特(比如UTF-8编码中,一个英文字符占用1个字节,而一个中文字符可能占用3个字节)。字符串在编程语言中是一个基本的数据类型,用于存储和处理文本数据。
- 字节串(Byte String):是由字节(byte)组成的序列,每个字节可以是0到255之间的任意值。字节串不关心字节的编码或它们代表的字符,它们只是原始的二进制数据。
-
存储内容:
- 字符串:存储的是字符数据,每个字符都有特定的编码(如ASCII、UTF-8等)。
- 字节串:存储的是原始的字节数据,不进行任何字符编码转换,可以包含任何二进制值。
-
使用场景:
- 字符串:用于存储和处理文本信息,如用户输入、文件内容等。
- 字节串:用于处理二进制数据,如文件的原始内容、网络传输的数据包等。
-
处理方式:
- 字符串:编程语言提供了丰富的字符串处理函数,如字符串拼接、查找、替换等。
- 字节串:处理方式更接近于数组或缓冲区,通常用于低级的数据操作,如内存拷贝、网络通信等。
-
编码与解码:
- 字符串:在不同编程语言中,字符串的编码方式可能不同,但通常都是以某种字符编码存储。
- 字节串:不涉及编码问题,它们是原始的字节流。
-
性能:
- 字符串:因为涉及到字符编码,处理字符串可能比处理字节串更复杂,性能上可能稍逊一筹。
- 字节串:由于直接操作字节,通常在性能上更优。
在不同的编程语言中,这两个概念的具体实现和表现可能有所不同,但基本的区别大致如上所述。
设置String类型的key同时设置过期时间
set <key1> <value> [ex 存活时长秒数] [px 存活时长毫秒数]
同时设置多个String类型的数据
mset : multi-set
mset <key1> <value> <key2> <value> <key3> <value> ...
同时查看多个String类型的数据
mset <key1> <key2> <key3> ...
查看String类型的数据的字符长度
strlen <key名>
查看要修改的key的原的值(输出在终端)同时修改key的值
getset <指定key> <新值>
只输出原key的值,同时改变原key的值
将key的值递增
将key的值+1
incr <指定key名>
将key的值+n
原key值是数字时
incrby <指定key名> <要增加的个数n>
# 以浮点单位的递增
incrbyfloat <指定key名> <要增加的数(如:+4.5)>
将key的值递减
将key的值-1
decr <指定key名>
将key的值-n
原key值是数字时
decrby <指定key名> <要减的个数n>
# 没有decrbyfloat这样的命令
将key的值的末尾追加内容
set key1 xxx
append key1 666
# 那么key1的值就为:xxx666
查看String类型的数据(字符串)的指定某一位到某一位的部分
注意0表示字符串的第一位
set key1 lotus43xxx
getrange key1 0 4
getrange key1 5 6
修改String类型的数据(字符串)的指定某一位的值
setrange key1 6 q
四、Redis中结构化value对象类型之Map类型及其操作
- Map型的value在Redis中又叫做Hash,它的最初实现是Hash表;一个Map可以包含若干个key-value,其中key不重复;
- Redis本身就是key-value结构,它的value可以是map类型,此类型的value内部又是一个subkey-subvalue,map内部的key和value不能再嵌套map了,它只能是String型所能表达的内容:整型、浮点型、字节串
Hash数据结构介绍
Hash数据结构
- 桶:bucket
- Hash函数,取模3
- 负载因子,扩容、缩容
map的主要操作
操作 | 描述 |
---|---|
hset | 设置哈希表中的单个或多个字段值。如果字段已存在,则会更新它的值;如果字段不存在,则会创建一个新的键值对。语法为hset key subkey_1 subvalue_1 [subkey_2 subvalue_2] ... [subkey_n subvlaue_n] |
hmset | 设置哈希表中的多个字段值 但是 从Redis 4.0.0开始,HMSET被废弃,请使用HSET代替。 |
hget | – |
hmget | – |
hgetall | – |
hkeys | – |
hvals | – |
hlen | – |
hdel | – |
由于map的value可以表示整数和浮点数,所以map也包含对特定的key的value做数字专有的操作,比如:
操作 | 描述 |
---|---|
hincrby | 可以原子地操作某个key对应的数字型value |
以下是上面操作的例子:
Redis Map(Hash)类型的实际应用例子
-
存储用户信息:
- 用户ID作为键,用户的属性(姓名、年龄、性别等)作为字段,避免将整个用户对象序列化成字符串。
-
配置项管理:
- 存储配置项,方便根据字段名快速访问和更新某个配置。
-
对象存储与缓存:
- 将数据原本存储在其他存储系统(如关系型数据库)中的数据缓存到Redis中,减少对原始数据源的访问压力并提高读取速度。例如,博客网站缓存文章的详细内容,使用
HSET
和HGET
命令存储和获取文章信息。
- 将数据原本存储在其他存储系统(如关系型数据库)中的数据缓存到Redis中,减少对原始数据源的访问压力并提高读取速度。例如,博客网站缓存文章的详细内容,使用
-
实时统计:
- 使用哈希来保存当前在线用户、页面浏览量和API请求次数等。例如,
HINCRBY
命令用于增加在线用户数或页面访问次数。
- 使用哈希来保存当前在线用户、页面浏览量和API请求次数等。例如,
五、Redis中结构化value对象类型之List类型及其操作(操作中有栈和队列的思想)
List即列表对象,用于存储String序列
针对单个key的元素的List类型的操作
操作 | 描述 |
---|---|
rpush/lpush | 将指定的String内容添加到给定key对应的列表value的开头或末尾,例如:rpush key1 "a" 操作将a这个字符串添加到列表尾,作为最后一个元素 |
rpop/lpop | 取出给定key对应的列表value的开头或末尾元素并删除之 |
lindex | 取出给定key对应的列表value的某个元素 |
lrange | 取出给定key对应的列表value的某个范围内的元素,例如lrange key1 0 9 取得key1对应的value的前10个元素 |
ltrim | 将给定key对应的列表value的某个范围内的元素剪下来(保留下来) |
trim:去除,剪掉 |
常用于消息队列
lpush: 在队列左边推入
rpop:弹出队列右边的第一个
rpush: 在队列右边推入
lpop:弹出队列左边的第一个
List类型的复杂的操作(方便类似生产者消费者模式场景的实现)
操作 | 描述 |
---|---|
blpop/brpop | 例如brpop key1 key2 60 指的是如果60秒内,key1非空则从key1对应的列表value中pop最右元素,否则从key2中pop,如果60秒内两个key始终为空,则超时返回 |
*拓展:生产者消费者模式
生产者消费者模式(Producer-Consumer Pattern)是一种并发设计模式,用于协调生产者和消费者之间的工作,以确保生产者生产的数据能够被消费者及时处理,同时避免数据的重复处理或丢失。这种模式在多线程环境中非常常见,尤其是在涉及到数据共享和线程同步的场景中。
核心概念
- 生产者(Producer):负责生成数据的线程或进程。
- 消费者(Consumer):负责处理数据的线程或进程。
- 缓冲区(Buffer):一个临时存储数据的容器,生产者将数据放入缓冲区,消费者从缓冲区取出数据进行处理。
模式特点
- 解耦生产者和消费者:生产者和消费者之间不需要直接通信,它们通过缓冲区进行数据交换,这有助于降低系统的耦合度。
- 线程安全:在多线程环境中,需要确保缓冲区的线程安全,避免数据竞争和条件竞争。
- 同步机制:通常需要使用同步机制(如锁、信号量、条件变量等)来控制对缓冲区的访问。
工作流程
- 生产者生产数据:生产者生成数据后,将其放入缓冲区。
- 缓冲区管理:缓冲区负责存储数据,并提供同步机制以确保数据的一致性。
- 消费者处理数据:消费者从缓冲区取出数据进行处理。
- 同步控制:当缓冲区满时,生产者可能需要等待;当缓冲区空时,消费者可能需要等待。
实现要点
- 锁(Locks):用于保护共享资源(如缓冲区)的访问,防止多个线程同时访问。
- 信号量(Semaphores):用于控制对共享资源的访问数量,可以用于控制缓冲区的容量。
- 条件变量(Condition Variables):用于线程间的协调,当某个条件满足时通知等待的线程。
示例代码(Python)
import threading
import time
import queue
# 定义一个缓冲区
buffer = queue.Queue(maxsize=10)
# 生产者
def producer():
for i in range(20):
time.sleep(1)
buffer.put(i)
print(f"Produced {i}")
# 消费者
def consumer():
while True:
item = buffer.get()
print(f"Consumed {item}")
buffer.task_done()
time.sleep(2)
# 创建线程
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)
# 启动线程
producer_thread.start()
consumer_thread.start()
# 等待线程结束
producer_thread.join()
buffer.join() # 等待所有数据被处理
consumer_thread.join()
在这个示例中,我们使用Python的queue.Queue
来实现缓冲区,它内部已经实现了线程安全的锁和条件变量。生产者线程生成数据并放入缓冲区,消费者线程从缓冲区取出数据进行处理。通过buffer.join()
确保所有数据都被处理完毕后再结束程序。
生产者消费者模式是并发编程中一个非常基础且重要的模式,它有助于提高程序的效率和响应性。
lpush
和rpush
命令用于给一个List类型的对象添加数据
rpop
和rpush
命令用于给一个List类型的对象删除数据
llen
命令用于查看一个List类型的对象有几个数据
lpush
推进去的数据需用rpop
弹出、rpush
推入的需用lpop
弹出
lindex
用于查看一个List类型的对象的(从左往右数)的第一个成员的值(0表示第一个成员)
lrange
命令用于查看一个List类型的对象的(从左往右数) 第几个成员到第几个成员的部分
0表示第一个元素
# 查看一个List类型的对象的所有内容
lrange <List对象名> 0 -1
linsert
用于在一个List类型对象中(从左往右数)的指定成员名的前或后插入一个成员
rpoplpush
复合命令,用于将一个List对象(从右边)弹出一个成员然后紧接着操作另一个List对象(在左边)推入这个成员进去
lrem
命令用于(从左往右数)删除指定次数的成员(如果有重复名的成员的话,那么count>1如果不是那么只写1)
lrem <List对象>
ltrim
命令用于保留List对象的(从左往右数)第几个到第几个的成员
lset
命令用于设置一个List对象的(从左往右数)第几个成员的值(0表示第一个成员)
lset <List对象>
Redis List类型的实际应用例子
-
消息队列:
- Redis的List类型可以通过
LPUSH
和RPUSH
(或者反过来,LPOP
和RPOP
)实现队列的功能,因此可以用Redis的List类型实现简单的消息队列。例如,使用LPUSH
将消息放入队列,使用RPOP
或BRPOP
弹出消息。
- Redis的List类型可以通过
-
排行榜:
LRANGE
命令可以分页查看队列中的数据,适合将每隔一段时间计算一次的排行榜存储在List类型中,例如京东每日的手机销量排行、学校每次月考学生的成绩排名等。
-
最新列表:
LPUSH
命令和LRANGE
命令能实现最新列表的功能,每次通过LPUSH
命令往列表里插入新的元素,然后通过LRANGE
命令读取最新的元素列表,如朋友圈的点赞列表、评论列表。
-
任务队列:
- Redis的列表数据结构可以用来实现任务队列,将需要处理的任务存储到列表中,然后通过消费者从列表中获取任务并进行处理,实现任务的异步处理和调度。
六、Redis结构化value对象类型之Set类型及其操作
Set类似List,但它是一个无序集合,其中的元素不重复
集合与其他数据结构的主要区别在于它的元素是唯一的,并且没有固定的顺序。而数组、表、树和图都可以存储有序元素或具有特定关系的数据。数组和表通常用于存储和访问结构化数据,树和图用于表示层次和网络关系。每种数据结构都有其特定的应用场景和优势,选择合适的数据结构可以提高程序的效率和性能。
集合(Set)在编程中有着广泛的应用场景,以下是一些常见的例子:
-
去重:
- 在处理数据时,经常需要去除重复的元素,例如从数据库查询结果中去除重复的记录,或者在处理用户输入时去除重复的选项。
-
数学集合操作:
- 在需要进行数学上的集合操作,如交集、并集、差集时,集合提供了直接的支持。
-
快速查找:
- 当需要快速判断某个元素是否存在于一个数据集中时,集合可以提供快速的查找功能。
-
权限控制:
- 在权限管理系统中,集合可以用来存储用户的角色或权限,方便进行权限的添加、删除和检查。
-
缓存实现:
- 集合可以作为缓存数据结构的一部分,存储最近访问或频繁访问的数据项。
-
对象属性检查:
- 在面向对象编程中,集合可以用来存储对象的属性或特征,方便进行属性的管理和检查。
-
唯一性保证:
- 在需要确保数据项唯一性的场合,如生成唯一的ID或序列号,集合可以用来存储已经使用过的值。
-
数据分片和分区:
- 在大数据应用中,集合可以用来将数据分片或分区,以便于并行处理。
-
配置管理:
- 在配置管理系统中,集合可以用来存储配置项,方便进行配置的添加、删除和查询。
-
推荐系统:
- 在推荐系统中,集合可以用来存储用户的兴趣点或标签,以便于生成个性化推荐。
-
社交网络分析:
- 在社交网络分析中,集合可以用来存储用户的好友列表或社交圈。
-
游戏开发:
- 在游戏开发中,集合可以用来管理游戏中的实体,如敌人、道具或玩家。
-
并发编程:
- 在并发编程中,集合可以作为线程安全的数据结构,用于同步和锁的管理。
-
测试和模拟:
- 在测试和模拟中,集合可以用来存储测试用例或模拟对象的状态。
-
算法实现:
- 许多算法,如排序、搜索、图算法等,都需要使用集合来存储中间结果或作为算法的一部分。
集合因其高效的元素管理和独特的性质,在软件开发中扮演着重要的角色。不同的编程语言提供了不同的集合实现,如Python的set和JavaScript的Set对象,它们都提供了丰富的API来支持集合操作。
set基本操作
操作 | 描述 |
---|---|
sadd/srem/sismember | 分别实现向set中增加、删除元素,以及检查某元素是否在set里 |
scard/smembers/srandmember | 分别实现统计元素个数、列出所有元素、随机获取元素 |
sinter/sunion/sdiff | 分别实现多个set的交集、并集和差集 |
sinterstore/sunionstore/sdiffstore | 分别实现将多个set的交集、并集、差集的结果储存在另一个key中 |
smove | 将set1的元素放入set2中 |
spop | 将集合的元素随机弹出删除(删除一个或多个) |
以下是上面这些操作的例子:
Redis中的Set的实际应用场景
Redis的Set(集合)是一种无序的、不重复的元素集合,它提供了丰富的操作命令,适用于多种实际应用场景。以下是一些Redis Set的典型应用:
-
去重:
- 在需要去除重复数据的场景中,如从日志中提取唯一的IP地址、从用户提交表单中提取唯一的邮箱地址等,可以使用Set的
SADD
命令添加元素,自动过滤掉重复项。
- 在需要去除重复数据的场景中,如从日志中提取唯一的IP地址、从用户提交表单中提取唯一的邮箱地址等,可以使用Set的
-
在线用户列表:
- 可以使用Set来存储当前在线的用户ID。每当用户登录时,使用
SADD
命令将用户ID添加到集合中;用户登出时,使用SREM
命令将用户ID从集合中移除。
- 可以使用Set来存储当前在线的用户ID。每当用户登录时,使用
-
标签系统:
- 在内容管理系统中,可以使用Set来存储文章或产品的标签。每个标签都是集合中的一个元素,而每篇文章或产品可以对应一个包含其所有标签的集合。
-
好友关系:
- 可以使用两个Set来表示用户的好友关系。例如,用户A的好友列表是一个Set,用户B的好友列表是另一个Set。检查两个用户是否为好友,只需要检查两个Set是否有交集。
-
抽奖活动:
- 在抽奖活动中,可以将参与者的标识(如用户ID或手机号)存储在一个Set中。使用
SRANDMEMBER
命令随机选择中奖者,确保随机性和唯一性。
- 在抽奖活动中,可以将参与者的标识(如用户ID或手机号)存储在一个Set中。使用
-
商品推荐:
- 在电商网站中,可以使用Set来存储用户感兴趣的商品ID集合。通过分析这些集合,可以发现用户的偏好,并进行个性化推荐。
-
分布式系统的唯一性问题:
- 在分布式系统中,Set可以用来确保任务的唯一性,例如,防止同一个任务被多个节点重复处理。
-
实时竞拍系统中的出价者列表:
- 在实时竞拍系统中,可以使用Set来存储对某个商品出价的用户ID,这样可以快速检查某个用户是否已经出价,以及快速获取当前所有出价者。
-
社交网络中的共同好友:
- 可以使用Set来找出两个用户之间的共同好友。对于用户A和用户B,分别存储他们的好友集合,然后使用
SINTER
命令求交集,得到共同好友列表。
- 可以使用Set来找出两个用户之间的共同好友。对于用户A和用户B,分别存储他们的好友集合,然后使用
-
库存管理:
- 在库存管理中,可以使用Set来跟踪不同仓库中的商品。通过
SUNION
命令,可以快速合并多个仓库的商品列表,进行库存盘点。
- 在库存管理中,可以使用Set来跟踪不同仓库中的商品。通过
-
投票系统:
- 在投票系统中,可以使用Set来存储已投票的用户ID,以确保每个用户只能投一次票。
Redis Set的这些应用场景展示了它在处理唯一性集合数据时的灵活性和效率。通过利用Set的特性,可以简化代码逻辑,提高系统性能。
七、Redis结构化value对象类型之Sorted-Set类型及其操作
Sorted-Set是Redis特有的数据类型,也是集合,但它是一个有序的key-value对**:
- key:在一个sorted-set中不重复
- value:是一个浮点数,称为score;可以与其他key相同
- 有序:sorted-set内部默认按照score从小到大排序
Sorted-Sort的基本操作
由于srted-set本省包含排序信息,在普通set的基础上,sroted-set新增了一系列和排序有关的操作:
Redis中的sorted-set(有序集合)是一种数据结构,它结合了集合(Set)的特性和可以对元素进行排序的能力。下面是Redis中sorted-set类型的具体操作和一些常用命令的详细说明:
zadd
- 用途:向有序集合添加一个或多个成员,或者更新已存在成员的分数。
- 语法:
ZADD key score1 member1 [score2 member2 ...]
- 示例:
这会将成员 “one”, “two”, 和 “three” 与对应的分数添加到名为ZADD myzset 1 "one" ZADD myzset 2 "two" ZADD myzset 3 "three"
myzset
的有序集合中。如果成员已存在,则更新其分数。
zrange
- 用途:通过索引区间返回有序集合指定区间内的成员。
- 语法:
ZRANGE key start stop [WITHSCORES]
- 示例:
这会返回有序集合ZRANGE myzset 0 -1 WITHSCORES
myzset
中所有成员及其分数,按分数从小到大排序。
revrange
- 用途:返回有序集中指定区间内的成员,通过索引,分数从高到低。
- 语法:
ZREVRANGE key start stop [WITHSCORES]
- 示例:
这会返回有序集合ZREVRANGE myzset 0 -1 WITHSCORES
myzset
中所有成员及其分数,按分数从大到小排序。
zrangebyscore
- 用途:通过分数返回有序集合指定区间内的成员。
- 语法:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
- 示例:
这会返回有序集合ZRANGEBYSCORE myzset 0 5 WITHSCORES
myzset
中分数在0到5之间的所有成员及其分数。
zrank
- **用途:**确定某个key值在本sorted-set内按照顺序排在第几位(从0开始)
- 语法:
zrank sort--set类型对象 <key名>
zrem
- 用途:移除有序集合中的一个或多个成员。
- 语法:
ZREM key member [member ...]
- 示例:
ZREM myzset "one"
这会从有序集合 myzset
中移除成员 “one”。
zincrby
- 用途:有序集合中对指定成员的分数加上增量。
- 语法:
ZINCRBY key increment member
- 示例:
这会将成员 “two” 的分数增加 5。ZINCRBY myzset 5 "two"
zcard
- 用途:获取有序集合的成员数。
- 语法:
ZCARD key
- 示例:
这会返回有序集合ZCARD myzset
myzset
中的成员数量。
zscore
- 用途:获取有序集合中指定成员的分数。
- 语法:
ZSCORE key member
- 示例:
这会返回成员 “two” 在有序集合ZSCORE myzset "two"
myzset
中的分数。
zremrangebyrank
- 用途:删除有序集合一定位置范围的一些元素
- 语法:
zremrangebyrank <sorted-set对象> <开始位> <结束位>
+inf
和-inf
以及limit
参数
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
key
:指定有序集合的键名。min
和max
:指定分数的最小值和最大值,可以是负无穷大-inf
和正无穷大+inf
,(inf:infinity)或者具体的数值。[WITHSCORES]
:可选参数,如果指定,命令会同时返回成员的分数。[LIMIT offset count]
:可选参数,用于限制返回结果的数量,offset
指定开始返回的位置,count
指定返回的数量。
Redis中的Sorted-Set的实际应用场景
Redis中的Sorted-Set(有序集合)是一种非常强大的数据结构,它在许多实际应用场景中都非常有用。以下是一些具体的应用场景:
-
排行榜系统:
- 游戏应用中的玩家排名、社交应用中的用户活跃度排名、电商应用中的商品销量排名等都可以使用Sorted-Set来实现。通过给每个用户或商品一个分数(比如分数、销量、活跃度等),可以很容易地根据分数对他们进行排序。使用
ZADD
命令添加或更新分数,ZREVRANGE
命令获取前N名的用户。
- 游戏应用中的玩家排名、社交应用中的用户活跃度排名、电商应用中的商品销量排名等都可以使用Sorted-Set来实现。通过给每个用户或商品一个分数(比如分数、销量、活跃度等),可以很容易地根据分数对他们进行排序。使用
-
延迟任务队列:
- Sorted-Set可以用于实现延迟任务队列。通过将任务的执行时间作为分数,任务的标识作为成员,将任务添加到Sorted-Set中。然后,可以通过
ZRANGEBYSCORE
命令查询到期的任务进行处理。
- Sorted-Set可以用于实现延迟任务队列。通过将任务的执行时间作为分数,任务的标识作为成员,将任务添加到Sorted-Set中。然后,可以通过
-
实时排行榜:
- 对于需要实时更新的排行榜,如股票价格排行、体育赛事得分排行等,Sorted-Set可以快速地添加新记录、更新现有记录,并能够通过分数区间查询来获取特定排名范围的数据。
-
多维度排序:
- 在一些场景下,可能需要根据多个维度对数据进行排序。例如,在一个应用商店中,除了根据下载量(分数)排序外,还可以根据最后更新时间进行次级排序。Sorted-Set可以通过组合这两个维度的值(例如,将下载量和更新时间戳连接起来)作为分数,从而实现多维度排序。
-
区间查询:
- Sorted-Set提供了
ZRANGE
和ZREVRANGE
命令,可以按照排行榜中的排名范围进行查询,例如查询前N名的成员。
- Sorted-Set提供了
-
商品销售排行榜:
- 使用Sorted-Set,其中分数为销售数量,value值为商品编号。可以通过
ZADD
添加商品销售记录,ZINCRBY
增加销量,ZRANGE
获取前N名热门商品。
- 使用Sorted-Set,其中分数为销售数量,value值为商品编号。可以通过
-
高并发下的统计分页显示:
- 在高并发场景下,使用Sorted-Set做统计分页显示,例如热评榜。使用时间作为分数插入,通过
ZRANGE
、ZREVRANGE
或ZRANGEBYSCORE
LIMIT按照分数查询分页。
- 在高并发场景下,使用Sorted-Set做统计分页显示,例如热评榜。使用时间作为分数插入,通过
这些应用场景展示了Redis Sorted-Set的灵活性和强大的功能,使其成为处理需要排序和排名的数据的理想选择。