redis系列:通过通讯录案例学习hash命令

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介:

前言

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

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

案例

demo功能是通讯录,整个demo的大致页面如下

准备工作

首先定义一个key的前缀,已经存储自增id的key

private static final String CONTACTS_KEY_PREFIX = "contacts:";
private static final String CONTACTS_ID_KEY = "contactsID";

通讯录相关的key将会以contacts:1、contacts:2、contacts:3的形式存储

redis操作对象

private RedisTemplate redisTemplate;
//string 命令操作对象
private ValueOperations valueOperations;
//hash 命令操作对象
private HashOperations hashOperatio

疑惑

如果读者和我一样是学Java的,刚听到hash时的第一反应是这个不是一个算法吗?当时我也是这样想的。那么先来看看hash在Redis中的结构,如下图(图片来源于Redis in Action)。

图片来源于Redis in Action

如果图看不懂的,我再来介绍下。其实Redis中的hash结构就和mysql中的表类似,把key当做表名,一张表中有多个列名(sub-key),每个列有自己的值(value),然后这张表只能存放一条数据。不过,这里的hash结构不会像mysql中固定好的,它可以很方便的增加删除列,例如增加sub-key3删除sub-key1.

新增

命令介绍

先来看看hash中关于新增的一些命令

命令 用例 描述
HSET HSET key field value 设置 key 指定的哈希集中指定字段的值。
HSETNX HSETNX key field value 当field不存在时,才能成功设置值
HMSET HMSET key field value [field value ...] 设置 key 指定的哈希集中指定字段的值(多个) 。

接下来看看demo中新增的功能,下图中点击+按钮,然后在弹出框中填入name和phone属性,点击提交后整个新增流程结束。

来看看后台的方法

@RequestMapping(value = "/add",method = RequestMethod.POST)
public boolean add(@RequestBody JSONObject contacts){
    //获取自增id
    Long contactsId = valueOperations.increment(CONTACTS_ID_KEY, 1);

    contacts.put("id",String.valueOf(contactsId));
    //json转map,然后存入redis
    hashOperations.putAll(CONTACTS_KEY_PREFIX+contactsId,contacts.getInnerMap());

    return true;
}
  1. 首先是获得自增id
  2. 然后将id存入到前端传过来的json对象中
  3. 调用hashOperations对象的putAll方法将对象传入到Redis中。(putAll方法其实是调用了hmset命令,源码如下)
public void putAll(K key, Map<? extends HK, ? extends HV> m) {
    if (!m.isEmpty()) {
        byte[] rawKey = this.rawKey(key);
        Map<byte[], byte[]> hashes = new LinkedHashMap(m.size());
        Iterator var5 = m.entrySet().iterator();

        while(var5.hasNext()) {
            Entry<? extends HK, ? extends HV> entry = (Entry)var5.next();
            hashes.put(this.rawHashKey(entry.getKey()), this.rawHashValue(entry.getValue()));
        }
        //调用hMSet
        this.execute((connection) -> {
            connection.hMSet(rawKey, hashes);
            return null;
        }, true);
    }
}

列表查询

命令介绍

同样先看看相关的获取值命令

命令 用例 描述
HGET HGET key field 返回 key 指定的哈希集中该字段所关联的值
HGETALL HGETALL key 返回 key 指定的哈希集中所有的字段和值。
HKEYS HKEYS key 返回 key 指定的哈希集中所有字段的名字。
HMGET HMGET key field [field ...] 返回 key 指定的哈希集中指定字段的值。
HVALS HVALS key 返回 key 指定的哈希集中所有字段的值。
HSCAN 用于迭代Hash类型中的键值对。
HGET和HGETALL命令

来看看HGET和HGETALL在redis客户端和java中是如何操作的

redis客户端执行的命令如下

hset key field1 "Hi"
hset key field1 "Hello"
hsetnx key field1 "Hello"
hsetnx key field2 " redis"
hget key field1
hgetall key

执行结果如下

下面是java代码

@Test
public void hGetAll() {
    jedis.hset("key", "field1", "Hi");
    redisTemplate.opsForHash().put("key", "field1", "Hello");

    System.out.println(jedis.hsetnx("key", "field1", "Hello"));
    System.out.println(redisTemplate.opsForHash().putIfAbsent("key", "field2", "Hello"));

    System.out.println(jedis.hget("key", "field1"));
    System.out.println(jedis.hgetAll("key"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().get("key", "field1"));
    System.out.println(redisTemplate.opsForHash().entries("key"));
}
HKEYS

redis客户端执行的命令如下

hset hashKey field1 value1
hset hashKey field2 value2
hkeys hashKey

执行结果如下

下面是java代码

@Test
public void hKeys() {
    jedis.hset("hashKey", "field1", "value1");
    jedis.hset("hashKey", "field2", "value2");

    System.out.println(jedis.hkeys("hashKey"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().keys("hashKey"));
    /**
     * 注:两次结果返回的顺序是不一样的,
     * 因为jedis.hkeys返回的是HashSet(内部使用HashMap)
     * redisTemplate.opsForHash().keys返回的是LinkHashSet(内部使用LinkHashMap)
     */
}
HVALS

redis客户端执行的命令如下

hmset key field1 value1 field2 value2 field3 value3
hvals key

执行结果如下

下面是java代码

@Test
public void hVals() {
    Map<String, String> map = new HashMap<>(3);
    map.put("field1", "value1");
    map.put("field2", "value2");
    map.put("field3", "value3");

    jedis.hmset("key", map);

    System.out.println(jedis.hvals("key"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().values("key"));
}

查询方法代码

接着写个查询方法,将新增的内容查询出来

@RequestMapping(value = "/getList",method = RequestMethod.GET)
    public List getList(){
        List list = new ArrayList();

        //获取联系人的keys
        Set<String> keys = redisTemplate.keys(CONTACTS_KEY_PREFIX+"*");

        for (String key: keys) {
            Map entries = hashOperations.entries(key);
            list.add(entries);
        }

        return list;
    }

这个hash查询多个会不方便些,步骤如下

  1. 获取相关的key
  2. 循环查找key相关的数据
  3. 将查询出来的结果添加到list中,返回

添加属性

来看看代码

@RequestMapping(value = "/addAttr", method = RequestMethod.POST)
public boolean addAttr(@RequestBody JSONObject contacts){
    String id = contacts.getString("id");
    String fieldName = contacts.getString("fieldName");
    String fieldValue = contacts.getString("fieldValue");

    hashOperations.put(CONTACTS_KEY_PREFIX+id, fieldName, fieldValue);

    return true;
}

其实就是用hset命令进行插入

hset contacts:1 address 北京9527号

删除属性

命令介绍

命令 用例 描述
HDEL HDEL key field [field ...] 从 key 指定的哈希集中移除指定的域

redis客户端执行的命令如下

hset hDelKey filed1 filedValue1
hdel hDelKey filed1
hdel hDelKey filed1

执行结果如下

现在来看看demo中的删除属性

代码如下

@RequestMapping(value = "/delAttr", method = RequestMethod.POST)
public boolean delAttr(@RequestBody JSONObject contacts){

    String id = contacts.getString("id");
    String fieldName = contacts.getString("fieldName");
    hashOperations.delete(CONTACTS_KEY_PREFIX+id, fieldName);

    return true;
}

其他命令

命令 用例 描述
HEXISTS HEXISTS key field 返回hash里面field是否存在
HINCRBY HINCRBY key field increment 增加 key 指定的哈希集中指定字段的数值
HINCRBYFLOAT HINCRBYFLOAT key field increment 同上,加的是浮点型
HLEN HLEN key 返回 key 指定的哈希集包含的字段的数量。
HSTRLEN HSTRLEN key field 返回hash指定field的value的字符串长度

建议学习的人最好每个命令都去敲下,加深印象。下面诗句送给你们。

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

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
18天前
|
NoSQL 应用服务中间件 API
Redis是如何建立连接和处理命令的
本文主要讲述 Redis 是如何监听客户端发出的set、get等命令的。
124 12
|
3月前
|
存储 NoSQL Redis
Redis 哈希(Hash)
10月更文挑战第16天
53 1
|
3月前
|
NoSQL Linux Redis
Docker学习二(Centos):Docker安装并运行redis(成功运行)
这篇文章介绍了在CentOS系统上使用Docker安装并运行Redis数据库的详细步骤,包括拉取Redis镜像、创建挂载目录、下载配置文件、修改配置以及使用Docker命令运行Redis容器,并检查运行状态和使用Navicat连接Redis。
397 3
|
2月前
|
存储 NoSQL Java
Redis命令:列表模糊删除详解
通过本文的介绍,我们详细探讨了如何在Redis中实现列表的模糊删除。虽然Redis没有直接提供模糊删除命令,但可以通过组合使用 `LRANGE`和 `LREM`命令,并在客户端代码中进行模糊匹配,来实现这一功能。希望本文能帮助你在实际应用中更有效地操作Redis列表。
91 0
|
3月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
50 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
3月前
|
缓存 NoSQL 测试技术
Redis如何解决频繁的命令往返造成的性能瓶颈!
Redis如何解决频繁的命令往返造成的性能瓶颈!
|
3月前
|
NoSQL Redis 数据安全/隐私保护
Redis 命令
10月更文挑战第15天
46 0
|
存储 NoSQL Redis
Redis学习一(基础入门).
一、前言     Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、key-Value 的数据库、并提供多种语言的API。     通常,Redis 将数据存储于内存中,或被配置为使用虚拟内存。
2523 0
|
17天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
161 85
|
3月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
87 6