赞
踩
本文今天主要是讲哈希(Hash)的方法的使用,以及redis对应的Java实现该怎么用。因为篇幅问题,我这里写了一个测试类,引入 RedisTemplate对象,后面例子里就不一一引入了。大家理解就行,如果大家还不知道如何通过Spring Boot 整合redis则可以查看我之前的文章:SpringBoot整合redis(redis支持单节点和集群)
package com.alian.datastruct; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; import java.util.concurrent.TimeUnit; @Slf4j @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest public class RedisHashTest { @Autowired private RedisTemplate<String, Object> redisTemplate; }
语法
HSET KEY_NAME FIELD VALUE
命令操作
127.0.0.1:6379> hset hash1 author alian
(integer) 1
127.0.0.1:6379> hget hash1 author
"alian"
Java操作
@Test
public void hSet() {
String redisKey = "hash1";
redisTemplate.delete(redisKey);
// 设置作者为alian
redisTemplate.opsForHash().put(redisKey, "author","alian");
// 获取缓存中的作者
Object author = redisTemplate.opsForHash().get(redisKey, "author");
log.info("获取到的作者的信息:{}", author);
}
获取到的作者的信息:alian
语法
HSETNX KEY_NAME FIELD VALUE
命令操作
127.0.0.1:6379> hsetnx hash2 title Redis
(integer) 1
127.0.0.1:6379> hsetnx hash2 title Java
(integer) 0
127.0.0.1:6379> hget hash2 title
"Redis"
Java操作
@Test
public void hSetNX() {
String redisKey = "hash2";
redisTemplate.delete(redisKey);
// 设置标题为Redis,如果title不存在
redisTemplate.opsForHash().putIfAbsent(redisKey, "title","Redis");
// 设置标题为Java,如果title不存在
// 此时title已存在了,设置失败
redisTemplate.opsForHash().putIfAbsent(redisKey, "title","Java");
// 获取缓存中的标题
Object author = redisTemplate.opsForHash().get(redisKey, "title");
log.info("获取到的标题的信息:{}", author);
}
获取到的标题的信息:Redis
语法
HGET KEY_NAME FIELD_NAME
命令操作
127.0.0.1:6379> hset hash3 title Redis
(integer) 1
127.0.0.1:6379> hget hash3 title
"Redis"
Java操作
@Test
public void hGet() {
String redisKey = "hash3";
redisTemplate.delete(redisKey);
// 设置标题为Redis为Redis
redisTemplate.opsForHash().put(redisKey, "title","Redis");
// 获取缓存中的标题
Object title = redisTemplate.opsForHash().get(redisKey, "title");
log.info("获取到的标题的信息:{}", title);
}
获取到的标题的信息:Redis
语法
HINCRBY KEY_NAME FIELD_NAME INCR_BY_NUMBER
HINCRBYFLOAT KEY_NAME FIELD_NAME INCREMENT
命令操作
127.0.0.1:6379> hincrby hash4 num 1 (integer) 1 127.0.0.1:6379> hincrby hash4 num 3 (integer) 4 127.0.0.1:6379> hincrby hash4 num -2 (integer) 2 127.0.0.1:6379> hget hash4 num "2" 127.0.0.1:6379> hincrbyfloat hash4 money 1.5 "1.5" 127.0.0.1:6379> hincrbyfloat hash4 money -0.5 "1" 127.0.0.1:6379> hgetall hash4 1) "num" 2) "2" 3) "money" 4) "1"
Java操作
@Test public void hIncByAndHIncByFloat() { String redisKey = "hash4"; redisTemplate.delete(redisKey); // 存储在哈希列表中的num加1 Long num1 = redisTemplate.opsForHash().increment(redisKey, "num", 1); log.info("存储在哈希列表中的num加1后的值:{}", num1); // 存储在哈希列表中的num加3 Long num2 = redisTemplate.opsForHash().increment(redisKey, "num", 3); log.info("存储在哈希列表中的num加3后的值:{}", num2); // 存储在哈希列表中的num减2 Long num3 = redisTemplate.opsForHash().increment(redisKey, "num", -2); log.info("存储在哈希列表中的num减2后的值:{}", num3); // 存储在哈希列表中的money加1.5 Double double1 = redisTemplate.opsForHash().increment(redisKey, "money", 1.5); log.info("存储在哈希列表中的money加1.5后的值:{}", double1); // 存储在哈希列表中的money减0.5 Double double2 = redisTemplate.opsForHash().increment(redisKey, "money", -0.5); log.info("存储在哈希列表中的money减0.5后的值:{}", double2); Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的值:{}", entries); }
存储在哈希列表中的num加1后的值:1
存储在哈希列表中的num加3后的值:4
存储在哈希列表中的num减2后的值:2
存储在哈希列表中的money加1.5后的值:1.5
存储在哈希列表中的money减0.5后的值:1.0
获取哈希列表的值:{num=2, money=1}
语法
HSTRLEN KEY_NAME FIELD_NAME
命令操作
127.0.0.1:6379> hset hash5 content "Redis is an open source"
(integer) 1
127.0.0.1:6379> hstrlen hash5 content
(integer) 23
127.0.0.1:6379> hstrlen hash5 num
(integer) 0
Java操作
@Test
public void hStrLen() {
String redisKey = "hash5";
redisTemplate.delete(redisKey);
// 设置内容content为:Redis is an open source
redisTemplate.opsForHash().put(redisKey, "content","Redis is an open source");
// 获取存储在哈希列表中的content的长度
Long length1 = redisTemplate.opsForHash().lengthOfValue(redisKey, "content");
log.info("获取存储在哈希列表中的content的长度:{}", length1);
Long length2 = redisTemplate.opsForHash().lengthOfValue(redisKey, "num");
log.info("获取存储在哈希列表中不存在的字段的长度:{}", length2);
}
获取存储在哈希列表中的content的长度:25
获取存储在哈希列表中不存在的字段的长度:0
语法
HEXISTS KEY_NAME FIELD_NAME
命令操作
127.0.0.1:6379> hset hash6 author alian
(integer) 1
127.0.0.1:6379> hexists hash6 author
(integer) 1
127.0.0.1:6379> hexists hash6 num
(integer) 0
Java操作
@Test
public void hExists() {
String redisKey = "hash6";
redisTemplate.delete(redisKey);
// 设置作者为alian
redisTemplate.opsForHash().put(redisKey, "author","alian");
Boolean hasAuthorKey = redisTemplate.opsForHash().hasKey(redisKey, "author");
log.info("判断哈希列表中author字段是否存在:{}", hasAuthorKey);
Boolean hasNumKey = redisTemplate.opsForHash().hasKey(redisKey, "num");
log.info("判断哈希列表中num字段是否存在:{}", hasNumKey);
}
判断哈希列表中author字段是否存在:true
判断哈希列表中num字段是否存在:false
语法
HDEL KEY_NAME FIELD1.. FIELDn
命令操作
127.0.0.1:6379> hset hash7 author alian (integer) 1 127.0.0.1:6379> hset hash7 title Redis (integer) 1 127.0.0.1:6379> hset hash7 content "Redis is an open source" (integer) 1 127.0.0.1:6379> hgetall hash7 1) "author" 2) "alian" 3) "title" 4) "Redis" 5) "content" 6) "Redis is an open source" 127.0.0.1:6379> hdel hash7 content (integer) 1 127.0.0.1:6379> hdel hash7 author title (integer) 2 127.0.0.1:6379> hgetall hash7 (empty list or set)
Java操作
@Test public void hDel() { String redisKey = "hash7"; redisTemplate.delete(redisKey); // 初始化数据 Map<String, Object> hashMap = new HashMap<>(); hashMap.put("author","alian"); hashMap.put("title","Redis"); hashMap.put("content","Redis is an open source"); redisTemplate.opsForHash().putAll(redisKey, hashMap); // 获取哈希列表的信息 Map<Object, Object> result = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的信息:{}", result); // 删除哈希列表中单个字段:content redisTemplate.opsForHash().delete(redisKey, "content"); // 删除哈希列表中单个字段:author,title redisTemplate.opsForHash().delete(redisKey, "author","title"); Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的信息:{}", entries); }
获取哈希列表的信息:{author=alian, title=Redis, content=Redis is an open source}
获取哈希列表的信息:{}
语法
HLEN KEY_NAME
命令操作
127.0.0.1:6379> hset hash8 author alian
(integer) 1
127.0.0.1:6379> hset hash8 title Redis
(integer) 1
127.0.0.1:6379> hset hash8 content "Redis is an open source"
(integer) 1
127.0.0.1:6379> hgetall hash8
1) "author"
2) "alian"
3) "title"
4) "Redis"
5) "content"
6) "Redis is an open source"
127.0.0.1:6379> hlen hash8
(integer) 3
Java操作
@Test public void hLen() { String redisKey = "hash8"; redisTemplate.delete(redisKey); // 初始化数据 Map<String, Object> hashMap = new HashMap<>(); hashMap.put("author","alian"); hashMap.put("title","Redis"); hashMap.put("content","Redis is an open source"); redisTemplate.opsForHash().putAll(redisKey, hashMap); // 获取哈希列表的信息 Map<Object, Object> result = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的信息:{}", result); // 获取哈希列表中字段数量 Long size = redisTemplate.opsForHash().size(redisKey); log.info("获取哈希列表中字段数量为:{}", size); }
获取哈希列表的信息:{author=alian, title=Redis, content=Redis is an open source}
获取哈希列表中字段数量为:3
语法
命令操作
127.0.0.1:6379> hmset hash9 author alian title Redis content "Redis is an open source"
OK
127.0.0.1:6379> hgetall hash9
1) "author"
2) "alian"
3) "title"
4) "Redis"
5) "content"
6) "Redis is an open source"
127.0.0.1:6379> hmget hash9 author title
1) "alian"
2) "Redis"
Java操作
@Test public void hmSetAndHmGet() { String redisKey = "hash9"; redisTemplate.delete(redisKey); // 初始化数据 Map<String, Object> hashMap = new HashMap<>(); hashMap.put("author","alian"); hashMap.put("title","Redis"); hashMap.put("content","Redis is an open source"); redisTemplate.opsForHash().putAll(redisKey, hashMap); // 获取哈希列表的信息 Map<Object, Object> result = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的信息:{}", result); List<Object> keys = Arrays.asList("author", "title"); // 获取哈希列表中多个字段的值 List<Object> list = redisTemplate.opsForHash().multiGet(redisKey, keys); log.info("获取哈希列表中多个字段的值:{}", list); }
获取哈希列表的信息:{author=alian, title=Redis, content=Redis is an open source}
获取哈希列表中多个字段的值:[alian, Redis]
语法
HKEYS KEY_NAME
命令操作
127.0.0.1:6379> hmset hash10 author alian title Redis content "Redis is an open source" OK 127.0.0.1:6379> hkeys hash10 1) "author" 2) "title" 3) "content" 127.0.0.1:6379> hvals hash10 1) "alian" 2) "Redis" 3) "Redis is an open source" 127.0.0.1:6379> hgetall hash10 1) "author" 2) "alian" 3) "title" 4) "Redis" 5) "content" 6) "Redis is an open source"
Java操作
@Test public void hKeysAndHValsAndHGetAll() { String redisKey = "hash10"; redisTemplate.delete(redisKey); // 初始化数据 Map<String, Object> hashMap = new HashMap<>(); hashMap.put("author","alian"); hashMap.put("title","Redis"); hashMap.put("content","Redis is an open source"); redisTemplate.opsForHash().putAll(redisKey, hashMap); // 获取哈希列表中所有的字段 Set<Object> keySet = redisTemplate.opsForHash().keys(redisKey); log.info("获取哈希列表中所有的字段:{}", keySet); // 获取哈希列表中所有的值 List<Object> valueList = redisTemplate.opsForHash().values(redisKey); log.info("获取哈希列表中所有的值:{}", valueList); // 获取哈希列表的信息 Map<Object, Object> result = redisTemplate.opsForHash().entries(redisKey); log.info("获取哈希列表的信息:{}", result); }
获取哈希列表中所有的字段:[author, title, content]
获取哈希列表中所有的值:[alian, Redis, Redis is an open source]
获取哈希列表的信息:{author=alian, title=Redis, content=Redis is an open source}
语法
HSCAN key cursor [MATCH pattern] [COUNT count]
Java操作
我先演示Java的实现,给哈希列表(hash11)插入2000个值,字段为hash-i,值为value-i,这里的 i 的取值从0到2000。
@Test public void hScan() { String redisKey = "hash11"; redisTemplate.delete(redisKey); Map<String, Object> hashMap = new HashMap<>(); for (int i = 0; i < 2000; i++) { hashMap.put("Java" + i, "value" + i); redisTemplate.opsForHash().put(redisKey, "Java-" + i, "value-" + i); } ScanOptions options = ScanOptions.scanOptions().match("Java*").count(100).build(); Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(redisKey, options); while (cursor.hasNext()) { Map.Entry<Object, Object> entry = cursor.next(); log.info("扫描到key:{},对应的value:{}", entry.getKey(), entry.getValue()); } }
命令操作
127.0.0.1:6379> hscan hash11 0 match Java* count 3 1) "1024" 2) 1) "Java-1826" 2) "\"value-1826\"" 3) "Java-722" 4) "\"value-722\"" 5) "Java-933" 6) "\"value-933\"" 127.0.0.1:6379> hscan hash11 1024 match Java* count 3 1) "256" 2) 1) "Java-1672" 2) "\"value-1672\"" 3) "Java-601" 4) "\"value-601\"" 5) "Java-1900" 6) "\"value-1900\"" 7) "Java-1461" 8) "\"value-1461\"" 9) "Java-934" 10) "\"value-934\"" 127.0.0.1:6379> hscan hash11 256 match Java* count 3 1) "1792" 2) 1) "Java-270" 2) "\"value-270\"" 3) "Java-118" 4) "\"value-118\"" 5) "Java-1244" 6) "\"value-1244\"" 127.0.0.1:6379>
先看官网的说明
虽然SCAN不能保证每次迭代返回的元素数量,但可以使用COUNT选项根据经验调整SCAN的行为。基本上,使用COUNT,用户指定了每次调用时要完成的工作量,以便从集合中检索元素。这只是对实现的一个提示,但一般来说,这是您在大多数情况下可以从实现中得到的。
重要提示:不需要对每个迭代使用相同的COUNT值。只要在下一次调用中传递的游标是在上一次调用该命令时获得的游标,调用方就可以根据需要将计数从一次迭代更改为另一次迭代。
第三点就是在Hash集合中使用HSCAN命令COUNT属性失效的原因。Redis配置文件中有两个和Hash类型ziplist相关的配置
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
也就是说
Hash集合的编码会由ziplist会转成dict,这个时候,HSCAN命令COUNT属性才会起效,当然此时Redis为Hash类型的数据会占用更多的内存空间。所以我这里插入了2000个数据演示这个游标,但是COUNT值不一定是那么多,有可能比这个多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。