redis系列:通过共同好友案例学习set命令

简介:

前言

这一篇文章将讲述Redis中的set类型命令,同样也是通过demo来讲述,其他部分这里就不在赘述了。

项目Github地址:https://github.com/rainbowda/learnWay/tree/master/learnRedis/case-set

案例

demo功能是共同好友,整个demo的大致页面如下。左边是存储到Redis中的数据,右边是从Redis中弹出的数据。

准备工作

首先定义一个存储a、b好友的key

private static final String A_FRIEND_KEY = "friend:a";

private static final String B_FRIEND_KEY = "friend:b";

redis操作对象

private RedisTemplate redisTemplate;
//string 命令操作对象
private ValueOperations valueOperations;
//set 命令操作对象
private SetOperations setOperations;

set在Redis中的结构可以看下图(图片来源于Redis in Action)。

图片来源于Redis in Action

添加好友

命令介绍

命令 用例 描述
SADD SADD key member [member ...] 添加一个或多个指定的member元素到集合的 key中

我们来看看demo中的新增功能,点击添加好友,往用户A里面添加一些好友。

添加完毕后,A有好友1、2、3,B有好友2、3、4。

后台java代码如下

@RequestMapping(value = "/addFriend", method = RequestMethod.POST)
public Long addFriend(String user, String friend) {
    String currentKey = A_FRIEND_KEY;
    if ("B".equals(user)) {
        currentKey = B_FRIEND_KEY;
    }
    //返回添加成功的条数
    return setOperations.add(currentKey, friend);
}

相同的redis命令如下

SADD friend:a 1 2 3
SADD friend:b 2 3 4

好友结构如下

删除好友

命令介绍

命令 用例 描述
SREM SREM key member [member ...] 在key集合中移除指定的元素

删除功能如下

后台java代码如下

@RequestMapping(value = "/delFriend", method = RequestMethod.DELETE)
public Long delFriend(String user, String friend) {
    String currentKey = A_FRIEND_KEY;
    if ("B".equals(user)) {
        currentKey = B_FRIEND_KEY;
    }
    //返回删除成功的条数
    return setOperations.remove(currentKey, friend);
}

相同的redis命令如下

SREM friend:b 5

列表查询

命令介绍

命令 用例 描述
SMEMBERS SMEMBERS key 返回key集合所有的元素.

后台java代码如下,分别查出A和B的好友,然后添加到map里

@RequestMapping(value = "/getList", method = RequestMethod.GET)
public Map getList() {
    Map map = new HashMap();

    Set aFriend = setOperations.members(A_FRIEND_KEY);
    Set bFriend = setOperations.members(B_FRIEND_KEY);

    map.put("aFriend", aFriend);
    map.put("bFriend", bFriend);

    return map;
}

相同的redis命令如下

SMEMBERS friend:a
SMEMBERS friend:b

共同好友

命令介绍

命令 用例 描述
SINTER SINTER key [key ...] 返回指定所有的集合的成员的交集.
SINTERSTORE SINTERSTORE destination key [key ...] 这个命令与SINTER命令类似, 但是它并不是直接返回结果集,而是将结果保存在 destination集合中.

页面如下,点击共同好友按钮,经过后台的数据获取,页面下方显示共同好友2、3。

共同好友也就是好友A和好友B共有的好友,两个数据做交集即可得到共有的数据,即A好友∩B好友={1,2,3}∩{2,3,4}={2,3} 。红色部分就是交集的结果

后台代码如下

@RequestMapping(value = "/intersectFriend", method = RequestMethod.GET)
public Set intersectFriend() {
    return setOperations.intersect(A_FRIEND_KEY, B_FRIEND_KEY);
}

相同的redis命令如下

SINTER friend:a friend:b

A独有的好友

命令介绍

命令 用例 描述
SDIFF SDIFF key [key ...] 返回一个集合与给定集合的差集的元素.
SDIFFSTORE SDIFFSTORE destination key [key ...] 该命令类似于 SDIFF命令, 不同之处在于该命令不返回结果集,而是将结果存放在destination集合中.

页面如下,点击A独有的好友按钮,经过后台的数据获取,页面下方显示独有的好友1。

A独有的好友也就是取出A的好友在B好友中没有出现过的,也就是取差集,即A好友-B好友={1,2,3}-{2,3,4}={1},下方图片中红色部分就是差集的结果。

后台java代码如下

@RequestMapping(value = "/differenceFriend", method = RequestMethod.GET)
public Set differenceFriend(String user) {
    return setOperations.difference(A_FRIEND_KEY, B_FRIEND_KEY);
}

相同的redis命令如下

SDIFF friend:a friend:b

所有的好友

命令介绍

命令 用例 描述
SUNION SUNION key [key ...] 返回给定的多个集合的并集中的所有成员.
SUNIONSTORE SUNIONSTORE destination key [key ...] 该命令作用类似于SUNION命令,不同的是它并不返回结果集,而是将结果存储在destination集合中.

页面如下,点击所有的好友按钮,经过后台的数据获取,页面下方显示共同好友1、2、3、4。

所有的好友就是A和B的好友,也就是A好友和B好友的并集,即A好友∪ B好友={1,2,3}∪ {2,3,4}={1,2,3,4},图片如下

后台java代码如下

@RequestMapping(value = "/unionFriend", method = RequestMethod.GET)
public Set unionFriend() {
    return setOperations.union(A_FRIEND_KEY, B_FRIEND_KEY);
}

相同的redis命令如下

SUNION friend:a friend:b

其他命令

命令 用例 描述
SCARD SCARD key 返回集合存储的key的基数 (集合元素的数量).
SISMEMBER SISMEMBER key member 返回成员 member 是否是存储的集合 key的成员.
SMOVE SMOVE source destination member 将member从source集合移动到destination集合中
SPOP SPOP key [count] 返回移除的一个或者多个key中的元素
SRANDMEMBER SRANDMEMBER key [count] 随机返回key集合中的一个或者多个元素
SSCAN SSCAN key cursor MATCH pattern 和scan类似

SCARD命令

返回集合存储的key的基数 (集合元素的数量).
SCARD key
返回值:集合的基数(元素的数量),如果key不存在,则返回 0.

redis客户端执行的命令如下

sadd sCardKey 1 2 3
scard sCardKey

下面是java代码

@Test
public void sCard() {
    jedis.sadd("sCardKey", "1", "2", "3");

    System.out.println(jedis.scard("sCardKey"));

    //spring redisTemplate
    System.out.println(setOperations.size("sCardKey"));
}

SISMEMBER命令

返回成员 member 是否是存储的集合 key的成员.
SISMEMBER key member
返回值:如果member元素是集合key的成员,则返回1。如果member元素不是key的成员,或者集合key不存在,则返回0

redis客户端执行的命令如下

 sadd sIsMemberKey hello
 sismember sIsMemberKey hello
 sismember sIsMemberKey redis

下面是java代码

@Test
public void sIsMember() {
    jedis.sadd("sIsMember", "hello");

    System.out.println(jedis.sismember("sIsMember", "hello"));

    //spring redisTemplate
    System.out.println(setOperations.isMember("sIsMember", "redis"));
}

SMOVE命令

将member从source集合移动到destination集合中. 对于其他的客户端,在特定的时间元素将会作为source或者destination集合的成员出现.
如果source 集合不存在或者不包含指定的元素,这smove命令不执行任何操作并且返回0.
否则对象将会从source集合中移除,并添加到destination集合中去,
如果destination集合已经存在该元素,则smove命令仅将该元素充source集合中移除.
如果source 和destination不是集合类型,则返回错误.
SMOVE source destination member
返回值:如果该元素成功移除,返回1。如果该元素不是 source集合成员,无任何操作,则返回0.

redis客户端执行的命令如下

sadd sMoveKeySrc 0 1 2 3 4
smove sMoveKeySrc sMoveKeyDst 5
smove sMoveKeySrc sMoveKeyDst 3
smembers sMoveKeyDst

执行结果如下

下面是java代码

@Test
public void sMove() {
    jedis.sadd("sMoveKeySrc", "0", "1", "2", "3", "4");

    System.out.println("移动一个不存在的元素,结果:"+jedis.smove("sMoveKeySrc", "sMoveKeyDst", "5"));

    //spring redisTemplate
    System.out.println("移动一个存在的元素,结果:" + setOperations.move("sMoveKeySrc","3", "sMoveKeyDst"));

    System.out.println(jedis.smembers("sMoveKeyDst"));
}

SPOP命令

移除且返回一个或多个随机元素
SPOP key [count]
返回值:移除的元素,当key不存在时返回nil

redis客户端执行的命令如下

sadd sPopKey 0 1 2 3 4
spop sPopKey
spop sPopKey 2
smembers sPopKey

执行结果如下

下面是java代码

@Test
public void sPop() {
    jedis.sadd("sPopKey", "0", "1", "2", "3", "4");

    System.out.println(jedis.spop("sPopKey"));

    //spring redisTemplate
    System.out.println(setOperations.pop("sPopKey", 2));

    System.out.println(jedis.smembers("sPopKey"));

}

SRANDMEMBER命令

仅提供key参数,那么随机返回key集合中的一个元素.
Redis 2.6开始, 可以接受 count 参数,
如果count是整数且小于元素的个数,返回含有 count 个不同的元素的数组,
如果count是个整数且大于集合中元素的个数时,仅返回整个集合的所有元素,
当count是负数,则会返回一个包含count的绝对值的个数元素的数组,
如果count的绝对值大于元素的个数,则返回的结果集里会出现一个元素出现多次的情况.
仅提供key参数时,该命令作用类似于SPOP命令, 不同的是SPOP命令会将被选择的随机元素从集合中移除, 而SRANDMEMBER仅仅是返回该随记元素,而不做任何操作.

SRANDMEMBER key [count]
返回值:不使用count 参数的情况下该命令返回随机的元素,如果key不存在则返回nil.使用count参数,则返回一个随机的元素数组,如果key不存在则返回一个空的数组.

redis客户端执行的命令如下

sadd sRandMemberKey 0 1 2 3 4
srandmember sRandMemberKey 2
srandmember sRandMemberKey 9
srandmember sRandMemberKey -2
srandmember sRandMemberKey -9

执行结果如下

下面是java代码

@Test
public void sRandMember() {
    jedis.sadd("sRandMemberKey", "0", "1", "2", "3", "4");

    System.out.println("未加count参数:" + jedis.srandmember("sRandMemberKey"));
    System.out.println("count是整数且小于元素的个数:" + jedis.srandmember("sRandMemberKey", 2));
    System.out.println("count是个整数且大于集合中元素的个数时:" + jedis.srandmember("sRandMemberKey", 9));
    System.out.println("count是整数且小于元素的个数:" + jedis.srandmember("sRandMemberKey", -2));
    System.out.println("count是个整数且大于集合中元素的个数时:" + jedis.srandmember("sRandMemberKey", -9));

    //spring redisTemplate默认支持重复的元素
    System.out.println("count是负数,且绝对值大于元素的个数:" + setOperations.randomMembers("sRandMemberKey", 9));
}

还是那句话建议学习的人最好每个命令都去敲下,加深印象。

纸上得来终觉浅,绝知此事要躬行。————出自《冬夜读书示子聿》

目录
相关文章
|
3月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
289 1
|
8月前
|
存储 缓存 监控
Redis设计与实现——Redis命令参考与高级特性
Redis 是一个高性能的键值存储系统,支持丰富的数据类型(字符串、列表、哈希、集合等)和多种高级功能。本文档涵盖 Redis 的核心命令分类,包括数据类型操作、事务与脚本、持久化、集群管理、系统监控等。特别介绍了事务的原子性特性、Lua 脚本的执行方式及优势、排序机制、发布订阅模型以及慢查询日志和监视器工具的使用方法。适用于开发者快速掌握 Redis 常用命令及其应用场景,优化系统性能与可靠性。
|
3月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
576 5
|
4月前
|
存储 缓存 NoSQL
Redis基础命令与数据结构概览
Redis是一个功能强大的键值存储系统,提供了丰富的数据结构以及相应的操作命令来满足现代应用程序对于高速读写和灵活数据处理的需求。通过掌握这些基础命令,开发者能够高效地对Redis进行操作,实现数据存储和管理的高性能方案。
146 12
|
4月前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
5月前
|
存储 缓存 人工智能
Redis六大常见命令详解:从set/get到过期策略的全方位解析
本文将通过结构化学习路径,帮助读者实现从命令语法掌握到工程化实践落地的能力跃迁,系统性提升 Redis 技术栈的应用水平。
|
6月前
|
NoSQL Redis
Lua脚本协助Redis分布式锁实现命令的原子性
利用Lua脚本确保Redis操作的原子性是分布式锁安全性的关键所在,可以大幅减少由于网络分区、客户端故障等导致的锁无法正确释放的情况,从而在分布式系统中保证数据操作的安全性和一致性。在将这些概念应用于生产环境前,建议深入理解Redis事务与Lua脚本的工作原理以及分布式锁的可能问题和解决方案。
245 8
|
8月前
|
存储 缓存 NoSQL
Redis中的常用命令-get&set&keys&exists&expire&ttl&type的详细解析
总的来说,这些Redis命令提供了处理存储在内存中的键值对的便捷方式。通过理解和运用它们,你可以更有效地在Redis中操作数据,使其更好地服务于你的应用。
511 17
|
8月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
3月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。