MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Redis集合命令SADD与SMEMBERS的使用技巧

2022-11-047.7k 阅读

Redis 集合简介

Redis 集合(Set)是 Redis 提供的一种数据结构,它是一个无序的字符串集合,集合中的每个元素都是唯一的,这意味着集合中不会出现重复的元素。这种数据结构在很多场景下都非常有用,比如去重、交集、并集、差集的计算等。

Redis 集合基于哈希表实现,添加、删除、查找的复杂度都是 O(1)。在底层实现上,当集合中的元素数量较少且每个元素的长度较短时,Redis 使用整数集合(intset)来存储集合元素,以节省内存空间。当元素数量增多或者元素长度变长时,会自动转换为哈希表结构来存储。

SADD 命令详解

SADD 命令基础语法

SADD key member [member ...] 这个命令用于将一个或多个成员元素加入到指定的集合中。如果给定的集合不存在,则会创建一个新的集合。如果成员元素已经存在于集合中,该元素将被忽略,因为集合的特性就是元素的唯一性。

SADD 命令的返回值

SADD 命令返回成功添加到集合中的新元素的数量。如果是因为元素已存在而未添加成功的情况,这些元素不会被计入返回值。

SADD 命令示例

以下是使用 Python 的 Redis 客户端库 redis - py 来演示 SADD 命令的示例代码:

import redis

# 连接到 Redis 服务器
r = redis.Redis(host='localhost', port=6379, db = 0)

# 使用 SADD 命令添加元素到集合
result = r.sadd('my_set', 'element1', 'element2', 'element3')
print(f"成功添加的新元素数量: {result}")

在上述代码中,首先通过 redis.Redis 方法连接到本地的 Redis 服务器。然后使用 sadd 方法将 element1element2element3 三个元素添加到名为 my_set 的集合中。最后打印出成功添加的新元素数量。

SADD 命令在实际场景中的应用

  1. 去重场景:在数据处理过程中,经常会遇到需要对数据进行去重的需求。例如,在爬虫程序中,需要记录已经爬取过的 URL 地址,以避免重复爬取。可以使用 SADD 命令将每个爬取到的 URL 添加到一个 Redis 集合中。由于集合的唯一性,重复的 URL 不会被重复添加。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

urls = ['http://example.com', 'http://another.com', 'http://example.com']
for url in urls:
    r.sadd('crawled_urls', url)
total_urls = r.scard('crawled_urls')
print(f"实际爬取的不同 URL 数量: {total_urls}")

在这段代码中,urls 列表包含了一些 URL,其中有重复的。通过 sadd 命令将这些 URL 添加到 crawled_urls 集合中,最后使用 scard 命令获取集合中的元素数量,即实际爬取的不同 URL 的数量。

  1. 标签系统:在社交媒体或者内容管理系统中,常常需要为用户、文章等添加标签。每个标签可以看作是集合中的一个元素。使用 SADD 命令可以方便地为某个对象添加标签。例如,为一篇文章添加标签:
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

article_id = 'article_1'
tags = ['python', 'database','redis']
for tag in tags:
    r.sadd(f'article:{article_id}:tags', tag)

在这个例子中,为 article_1 这篇文章添加了 pythondatabaseredis 三个标签。通过这种方式,可以很方便地对文章进行分类和检索。

SMEMBERS 命令详解

SMEMBERS 命令基础语法

SMEMBERS key 该命令用于返回指定集合中的所有成员元素。由于集合是无序的,所以返回的元素顺序也是不确定的。

SMEMBERS 命令的返回值

SMEMBERS 命令返回一个包含集合中所有成员元素的列表。如果指定的集合不存在,则返回一个空列表。

SMEMBERS 命令示例

同样使用 redis - py 库来演示 SMEMBERS 命令的使用:

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 添加一些元素到集合
r.sadd('my_set','member1','member2','member3')

# 获取集合中的所有元素
members = r.smembers('my_set')
print(f"集合中的元素: {members}")

在上述代码中,先向 my_set 集合中添加了 member1member2member3 三个元素,然后使用 smembers 方法获取集合中的所有元素并打印出来。

SMEMBERS 命令在实际场景中的应用

  1. 获取用户标签:在前面提到的标签系统示例中,如果需要获取某篇文章或者某个用户的所有标签,可以使用 SMEMBERS 命令。例如:
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

article_id = 'article_1'
tags = r.smembers(f'article:{article_id}:tags')
print(f"文章 {article_id} 的标签: {tags}")

这段代码获取了 article_1 文章的所有标签并打印出来。

  1. 数据分析:在一些数据分析场景中,可能需要获取某个集合中的所有数据来进行进一步的分析。比如,在一个电商网站中,可能有一个集合存储了所有购买过某类商品的用户 ID。通过 SMEMBERS 命令获取这些用户 ID 后,可以进行用户行为分析、用户画像等操作。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

product_category = 'electronics'
user_ids = r.smembers(f'users_who_bought:{product_category}')
print(f"购买过 {product_category} 类商品的用户 ID: {user_ids}")

这里获取了购买过电子产品类商品的所有用户 ID,为后续的数据分析提供了基础数据。

SADD 和 SMEMBERS 命令结合使用技巧

  1. 实时统计活跃用户:在一个在线游戏或者社交平台中,需要实时统计当前活跃的用户。可以在用户登录时使用 SADD 命令将用户 ID 添加到一个名为 active_users 的集合中,在用户登出时从集合中移除(这里暂不详细讨论移除命令)。然后通过 SMEMBERS 命令可以随时获取当前所有活跃用户的列表,也可以使用 scard 命令获取活跃用户的数量。
import redis
import time

r = redis.Redis(host='localhost', port=6379, db = 0)

# 模拟用户登录
user_ids = ['user1', 'user2', 'user3']
for user_id in user_ids:
    r.sadd('active_users', user_id)

# 模拟一段时间后查看活跃用户
time.sleep(5)
active_users = r.smembers('active_users')
print(f"当前活跃用户: {active_users}")

在这个示例中,首先模拟了三个用户登录,将他们的 ID 添加到 active_users 集合中。然后通过 time.sleep 模拟了一段时间的流逝,最后获取并打印出当前的活跃用户列表。

  1. 构建推荐系统:在推荐系统中,可以利用集合的特性来构建用户兴趣模型。比如,每个用户喜欢的商品类别可以存储在一个集合中。通过 SADD 命令添加用户喜欢的商品类别,然后通过 SMEMBERS 命令获取用户喜欢的所有商品类别。基于这些信息,可以为用户推荐相似类别的商品。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

user_id = 'user_1'
liked_categories = ['clothes','shoes', 'accessories']
for category in liked_categories:
    r.sadd(f'user:{user_id}:liked_categories', category)

# 获取用户喜欢的商品类别
user_liked_categories = r.smembers(f'user:{user_id}:liked_categories')
print(f"用户 {user_id} 喜欢的商品类别: {user_liked_categories}")

在这个例子中,为 user_1 用户添加了喜欢的商品类别,并获取了这些类别。基于这些信息,可以进一步分析用户兴趣,为用户推荐相关商品。

SADD 和 SMEMBERS 命令的性能考虑

  1. SADD 命令性能:由于 Redis 集合的底层实现,当集合元素数量较少且元素长度较短时,SADD 命令的执行效率非常高,因为此时使用的是整数集合结构,添加元素的时间复杂度为 O(1)。但当集合元素数量增多或者元素长度变长,集合转换为哈希表结构存储时,虽然平均时间复杂度仍然是 O(1),但可能会因为哈希表的扩容等操作导致偶尔的性能抖动。所以在设计应用时,如果预计集合元素数量会非常大,需要提前考虑这种情况。
  2. SMEMBERS 命令性能:SMEMBERS 命令在集合元素数量较少时性能很好。然而,当集合元素数量非常大时,获取所有成员元素会消耗较多的网络带宽和客户端内存。因为该命令会一次性返回集合中的所有元素,如果集合中有大量元素,可能会导致网络拥塞和客户端内存溢出等问题。在这种情况下,可以考虑使用 SSCAN 命令来增量式地获取集合元素,而不是一次性获取所有元素。

与其他 Redis 集合命令的配合使用

  1. SREM 命令SREM key member [member ...] 用于从指定集合中移除一个或多个成员元素。在前面提到的实时统计活跃用户场景中,用户登出时就可以使用 SREM 命令从 active_users 集合中移除用户 ID。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

user_id = 'user1'
r.srem('active_users', user_id)
print(f"用户 {user_id} 已从活跃用户集合中移除")
  1. SISMEMBER 命令SISMEMBER key member 用于判断指定成员元素是否存在于集合中。在添加元素到集合之前,可以使用 SISMEMBER 命令先判断元素是否已经存在,避免不必要的 SADD 操作。例如,在爬虫程序中,可以在添加 URL 到已爬取 URL 集合之前先判断该 URL 是否已存在。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

url = 'http://example.com'
if not r.sismember('crawled_urls', url):
    r.sadd('crawled_urls', url)
    print(f"URL {url} 已添加到已爬取 URL 集合")
else:
    print(f"URL {url} 已存在于已爬取 URL 集合")
  1. SCARD 命令SCARD key 用于获取集合中的元素数量。在很多场景下,比如统计活跃用户数量、已爬取 URL 数量等,都可以使用 SCARD 命令。结合前面的实时统计活跃用户场景,使用 SCARD 命令可以方便地获取当前活跃用户的数量。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

active_user_count = r.scard('active_users')
print(f"当前活跃用户数量: {active_user_count}")

通过深入理解和灵活运用 Redis 集合的 SADD 和 SMEMBERS 命令,以及与其他相关命令的配合使用,可以在各种应用场景中高效地处理数据,充分发挥 Redis 集合数据结构的优势。无论是去重、标签管理、实时统计还是推荐系统等领域,这些命令都能提供强大的支持。同时,在使用过程中要注意性能问题,根据实际情况选择合适的操作方式,以确保系统的高效稳定运行。在实际开发中,还需要结合具体的业务需求和系统架构,对 Redis 集合的使用进行优化和调整,以达到最佳的应用效果。