Redis增删改查、复杂查询案例分析
-
Redis 基本操作(增删改查)
- 插入(增)操作
- 字符串(String)类型插入:在 Redis 中,使用
SET
命令插入一个字符串类型的键值对。例如,SET user:name "John"
,这里user:name
是键,"John"
是值。它可以用来存储用户的姓名、配置信息等简单的文本数据。 - 哈希(Hash)类型插入:哈希类型适合存储对象。例如,存储一个用户对象的信息,可以使用
HSET
命令。HSET user:1 name "Alice" age 25 email "alice@example.com"
,这表示在user:1
这个键对应的哈希中,设置name
字段为"Alice"
,age
字段为25
,email
字段为alice@example.com
。 - 列表(List)类型插入:列表类型用于存储有序的元素序列。使用
LPUSH
或RPUSH
命令插入元素。LPUSH mylist "apple" "banana"
表示向左(头部)插入元素"apple"
和"banana"
到mylist
列表中,RPUSH
则是向右(尾部)插入。 - 集合(Set)类型插入:集合用于存储无序的、不重复的元素。
SADD myset "a" "b" "c"
将元素"a"
、"b"
和"c"
添加到myset
集合中。 - 有序集合(Sorted Set)类型插入:有序集合不仅存储元素,还存储元素的分数(用于排序)。
ZADD myzset 1 "element1" 2 "element2"
将"element1"
和"element2"
添加到myzset
有序集合中,分数分别为1
和2
。
- 字符串(String)类型插入:在 Redis 中,使用
- 查询操作
- 字符串(String)类型查询:使用
GET
命令查询字符串类型的值。例如,GET user:name
会返回之前设置的"John"
。 - 哈希(Hash)类型查询:
HGET
用于获取哈希中的一个字段的值,如HGET user:1 name
返回"Alice"
。HGETALL
则返回哈希中的所有字段和值,例如HGETALL user:1
会返回{name: "Alice", age: 25, email: "alice@example.com"}
(以伪代码形式展示返回格式)。 - 列表(List)类型查询:
LRANGE
命令用于获取列表中的元素范围。例如,LRANGE mylist 0 -1
会返回整个mylist
列表的所有元素。LLEN
可以查询列表的长度。 - 集合(Set)类型查询:
SMEMBERS
返回集合中的所有元素,如SMEMBERS myset
返回{"a", "b", "c"}
。SISMEMBER
用于判断一个元素是否在集合中,如SISMEMBER myset "a"
返回1
(表示存在)。 - 有序集合(Sorted Set)类型查询:
ZRANGE
按分数从小到大的顺序返回有序集合中的元素范围,如ZRANGE myzset 0 -1
返回按分数排序后的元素。ZSCORE
获取一个元素的分数,如ZSCORE myzset "element1"
返回1
。
- 字符串(String)类型查询:使用
- 更新操作
- 字符串(String)类型更新:再次使用
SET
命令即可更新字符串的值。例如,SET user:name "Bob"
将之前的"John"
更新为"Bob"
。 - 哈希(Hash)类型更新:使用
HSET
命令更新哈希中的字段值。如HSET user:1 age 26
将user:1
这个用户对象的年龄更新为26
。 - 列表(List)类型更新:可以使用
LSET
命令更新列表中的元素。例如,LSET mylist 0 "new_apple"
将mylist
列表头部的"apple"
更新为"new_apple"
(前提是列表长度足够)。 - 集合(Set)类型更新:集合本身无序且元素不重复,更新操作主要是添加新元素(
SADD
)或者删除元素(SREM
)来间接更新集合的内容。 - 有序集合(Sorted Set)类型更新:可以使用
ZADD
重新添加元素来更新其分数,或者使用ZINCRBY
来增加元素的分数,如ZINCRBY myzset 1 "element1"
将"element1"
的分数增加1
。
- 字符串(String)类型更新:再次使用
- 删除操作
- 字符串(String)类型删除:使用
DEL
命令删除字符串类型的键值对。例如,DEL user:name
将删除user:name
这个键及其对应的值。 - 哈希(Hash)类型删除:
HDEL
用于删除哈希中的一个或多个字段。如HDEL user:1 email
删除user:1
这个用户对象的email
字段。也可以使用DEL
删除整个哈希键。 - 列表(List)类型删除:
LPOP
和RPOP
分别从列表的头部和尾部删除一个元素。例如,LPOP mylist
删除mylist
列表头部的元素。LREM
可以根据元素的值删除指定数量的元素。 - 集合(Set)类型删除:
SREM
用于删除集合中的一个或多个元素。例如,SREM myset "a"
从myset
集合中删除元素"a"
。 - 有序集合(Sorted Set)类型删除:
ZREM
用于删除有序集合中的一个或多个元素。如ZREM myzset "element1"
删除myzset
中的"element1"
元素。
- 字符串(String)类型删除:使用
- 插入(增)操作
-
复杂查询案例分析
- 案例一:用户登录系统中的 Redis 应用
- 场景描述:在一个用户登录系统中,需要存储用户的登录状态、最近登录时间、权限信息等。同时,为了实现用户的单点登录(一个用户只能在一个设备上登录),需要对用户的登录设备进行管理。
- 数据结构选择与操作
- 存储用户登录状态和最近登录时间:可以使用字符串类型来存储用户的登录状态(
SET user:1:login_status "logged_in"
)和最近登录时间(SET user:1:last_login_time "2024-01-01 12:00:00"
)。 - 存储用户权限信息:哈希类型适合存储用户权限信息。例如,
HSET user:1:permissions read true write false admin false
表示用户1
有读取权限,没有写入和管理员权限。 - 实现单点登录管理:使用集合类型存储登录的用户设备。当用户在新设备登录时,首先检查集合中是否已经存在该用户的登录设备记录。如果存在,说明该用户在其他设备上已经登录,可能需要采取相应的措施(如强制下线旧设备)。可以使用
SADD user:1:login_devices "device_id_1"
来添加登录设备,使用SISMEMBER user:1:login_devices "device_id_1"
来检查设备是否已经登录。
- 存储用户登录状态和最近登录时间:可以使用字符串类型来存储用户的登录状态(
- 复杂查询示例
- 查询用户的所有权限信息:使用
HGETALL user:1:permissions
来获取用户1
的所有权限信息。 - 检查用户是否在特定设备上登录并且具有写入权限:首先使用
SISMEMBER user:1:login_devices "device_id_1"
检查用户是否在device_id_1
设备上登录,然后使用HGET user:1:permissions write
检查是否具有写入权限。
- 查询用户的所有权限信息:使用
- 案例二:电商系统中的商品推荐和购物车管理
- 场景描述:在电商系统中,需要根据用户的浏览历史和购买历史推荐商品,同时管理用户的购物车。
- 数据结构选择与操作
- 存储用户浏览历史和购买历史:对于用户的浏览历史,可以使用列表类型存储。每次用户浏览一个商品,使用
LPUSH user:1:browse_history product_id_1
将商品 ID 添加到用户1
的浏览历史列表头部。对于购买历史,同样可以使用列表类型,如LPUSH user:1:purchase_history product_id_2
。 - 商品推荐计算(简单示例):根据用户的浏览历史和购买历史,可以通过统计商品出现的频率来进行推荐。可以定期(如每天晚上)对数据进行处理,将浏览历史和购买历史合并到一个列表中,然后使用 Redis 的
SORT
命令或者在应用层进行统计分析,找出出现频率较高的商品作为推荐商品。 - 购物车管理:使用哈希类型来管理购物车。例如,
HSET user:1:cart product_id_3 quantity 2
表示用户1
的购物车中有2
个product_id_3
商品。
- 存储用户浏览历史和购买历史:对于用户的浏览历史,可以使用列表类型存储。每次用户浏览一个商品,使用
- 复杂查询示例
- 查询用户购物车中的商品数量和总价(假设已知商品价格):首先使用
HGETALL user:1:cart
获取购物车中的所有商品信息,然后根据商品 ID 查询商品价格(可以从数据库或者其他存储中获取),计算出总价和商品数量。 - 根据用户浏览历史和购买历史推荐前 3 个商品:首先将浏览历史和购买历史合并到一个列表(假设为
user:1:history
),然后可以使用类似于以下的方式(以伪代码形式)进行统计推荐:from collections import Counter # 获取用户历史记录(假设已经合并) history_list = redis_client.lrange("user:1:history", 0, -1) # 统计商品出现的频率 product_count = Counter(history_list) # 获取出现频率最高的3个商品 top_3_products = product_count.most_common(3)
- 查询用户购物车中的商品数量和总价(假设已知商品价格):首先使用
- 案例三:社交网络系统中的关系管理和动态推送
- 场景描述:在社交网络系统中,需要管理用户之间的好友关系、用户发布的动态以及根据好友关系进行动态推送。
- 数据结构选择与操作
- 存储好友关系:使用集合类型来存储用户的好友关系。例如,
SADD user:1:friends user:2 user:3
表示用户1
的好友是用户2
和用户3
。 - 存储用户动态:可以使用列表类型存储用户发布的动态。例如,
LPUSH user:1:posts "I just had a great day!"
表示用户1
发布了一条动态。 - 动态推送计算(简单示例):当用户发布一条动态时,需要将这条动态推送给该用户的所有好友。可以遍历该用户的好友集合,将动态 ID(可以是动态在列表中的索引或者其他唯一标识)添加到每个好友的动态推送列表中。
- 存储好友关系:使用集合类型来存储用户的好友关系。例如,
- 复杂查询示例
- 查询用户的好友数量和好友列表:使用
SCARD user:1:friends
查询用户1
的好友数量,使用SMEMBERS user:1:friends
查询好友列表。 - 查询用户的最新动态和好友的最新动态:使用
LRANGE user:1:posts 0 0
查询用户1
的最新动态。对于好友的最新动态,可以遍历好友列表,对每个好友使用类似的方法获取最新动态,然后按照时间顺序(发布动态的顺序)进行排序展示。
- 查询用户的好友数量和好友列表:使用
- 案例一:用户登录系统中的 Redis 应用