Redis数据结构--哈希hash

  如果内存足够大 ,那么一个 Redis 的 hash 结构可以存储2的32次方-1个键值对 ( 40多亿)。

       在 Redis 中, hash 是一个 String 类型的 field 和 value 的映射表,因此存储的数据实际在 Redis 内存中都是一个字符串。

       假设User有三个字段: id name sex

       在 Redis 中它就是一个这样的结构,其中 user代表的是 hash 结构在 Redis 内存的 key,通过就可以找到这个 hash 结构,而 hash 结构由一系列的 field 和 value 组成

       

       hash 结构命令

       

                   

  在 Redis 中的哈希结构和字符串的不同:

  首先,命令都是以 h 开头,代表操作的是 hash 结构

  其次,大多数命令多一个层级 field,这是hash 结构的一个内部键,也就是说Redis 需要通过 key 索引到对应的 hash 结构,再通过 field来确定使用 hash 结构的哪个键值对
  注意事项:

  哈希结构的大小,如果哈希结构是个很大的键值对,那么使用它要十分注意。 尤其是关于 hkeys 、 hgetall 、 hvals 等返回所有哈希结构数据的命令,会造成大量数据的读取。这需要考虑性能和读取数据大小对 JVM 内存的影响 。
  对于数字的操作命令 hincrby 而言,要求存储的也是整数型的字符串
  对于hincrbyfloat 而言,则要求使用浮点数或者整数,否则命令会失败。

       Spring操作hash

package com.smart;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;

public class RedisStringDemo {

    public static void main(String[] args){
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:redis/spring-redis.xml");

        // redisTemplate.opsForValue()所返回的对象可以操作简单的键值对,可以是字符串,也可以是对象,具体依据所配置的序列化方案
        // 在spring-redis-string.xml中key和value是指定的 stringRedisSerializer
        RedisTemplate redisTemplate= (RedisTemplate<String, String>) context.getBean("redisTemplate");

        flushDb(redisTemplate);

        String key="role";
        Map<String, String> map = new HashMap<String, String>();
        map.put("id","11");
        map.put("name","jim");
        map.put("age",String.valueOf("18"));
        redisTemplate.opsForHash().putAll(key,map);

        redisTemplate.opsForHash().put(key,"sex","male");

        Boolean isExist = redisTemplate.opsForHash().hasKey(key, "name");
        System.out.println(key+"是否存在name这个属性:"+isExist);

        Map<String,String> entries = redisTemplate.opsForHash().entries(key);
        if(entries !=null){
            printMap(entries);
        }

        redisTemplate.opsForHash().put(key, "k4", "6");
        System.out.println(redisTemplate.opsForHash().increment(key,"id",3));
        System.out.println(redisTemplate.opsForHash().increment(key,"k4",3.4));

        Set<String> set = redisTemplate.opsForHash().keys(key);
        for(String str: set){
            System.out.println(str);
        }

        List<String> list = new ArrayList<>();
        list.add("id");
        list.add("name");
        list.add("age");
        List<String> multiGet = redisTemplate.opsForHash().multiGet(key, list);
        printList(multiGet);

        System.out.println(redisTemplate.opsForHash().size(key));

        System.out.println(redisTemplate.opsForHash().putIfAbsent(key,"id","test"));

        System.out.println(redisTemplate.opsForHash().putIfAbsent(key,"sex","text"));
    }

    public static void printMap(Map<String,String> map){
        for(Map.Entry<String,String> entry : map.entrySet()){
            System.out.println("key= "+entry.getKey()+", value="+entry.getValue());
        }
    }

    public static void printList(List<String> list){
        for(String s: list){
            System.out.println(s);
        }
    }

    public static String flushDb(RedisTemplate<String,String> redisTemplate){
      return redisTemplate.execute(new RedisCallback<String>() {
          @Override
          public String doInRedis(RedisConnection connection) throws DataAccessException {
              connection.flushDb();
              return "ok";
          }
      });
    }

}

  在 Spring 中使用 redisTemplate.opsForHash().putAll(key, map )方法相当于执行了hmset 命令,使用了 map ,由于配置了默认的序列化器为字符串,所以它也只会用字符串进行转化,这样才能执行对应的数值加法,如果使用其他序列化器,则后面的命令可能会抛出异常。

  在使用大的 hash 结构时,需要考虑返回数据的大小,以避免返回太多的数据,引发JVM内存溢出或者 Redis 的性能问题。

  参考:
  原文:https://artisan.blog.csdn.net/article/details/82788441

 

posted on 2019-02-24 19:54  溪水静幽  阅读(863)  评论(0)    收藏  举报