简体   繁体   English

如何使用 JAVA 在 Redis 中进行批量插入?

[英]How to do Mass insertion in Redis using JAVA?

Hi I need to do multiple insertions of the form嗨,我需要多次插入表格

SADD key value SADD 键值

I have the key value pair and needed to know how to perform mass insertions using JAVA.我有键值对,需要知道如何使用 JAVA 执行批量插入。 I have written a file in the Redis Protocol.我在 Redis 协议中编写了一个文件。 How to proceed further如何进一步进行

If you have inputs written to Redis protocol format then why don't just use pipe mode of redis-cli or nc?如果您已将输入写入 Redis 协议格式,那么为什么不只使用 redis-cli 或 nc 的管道模式? It's explained from http://redis.io/topics/mass-insert .它的解释来自http://redis.io/topics/mass-insert

If you have mass (key, value) inputs then you can use Jedis to perform sadd with pipelining to get higher performance.如果您有大量(键、值)输入,那么您可以使用 Jedis 使用流水线执行 sadd 以获得更高的性能。

Below example assumes that iter (Iterator) has elements each item is key"\\t"value form.下面的例子假设迭代器(Iterator)有元素,每一项都是键“\\t”值的形式。

try (Jedis jedis = new Jedis(host, port)) {
  Pipeline pipeline = jedis.pipelined();
  while (iter.hasNext()) {
    String[] keyValue = iter.next().split("\t");
    pipeline.sadd(keyValue[0], keyValue[1]);
    // you can call pipeline.sync() and start new pipeline here if you think there're so much operations in one pipeline
  }
  pipeline.sync();
}

If you are doing the actual read/write operations through Spring CacheManager with RedisTemplate configured to use Redis as the cache, you can also use the executePipelined method of RedisTemplate which takes a callback as an argument.如果您通过 Spring CacheManager进行实际的读/写操作,并且将RedisTemplate配置为使用 Redis 作为缓存,您还可以使用RedisTemplate 的 executePipelined方法,该方法将回调作为参数。 The callback needs to define the doInRedis method which does the work (read/write operations) in Redis that you want to do in a batch.回调需要定义doInRedis方法,该方法在 Redis 中执行您要批量执行的工作(读/写操作)。

Following code shows inserting a List of objects wrapped in a CacheableObject interface that has a getKey() and getValue() by calling redisTemplate.opsForHash().put() .以下代码显示了通过调用redisTemplate.opsForHash().put()插入包含在具有 getKey() 和 getValue() 的 CacheableObject 接口中的对象列表。

@Component
public class RedisClient {
  @Autowired
  RedisTemplate redisTemplate;  
  
  //batch-insert using Redis pipeline, a list of objects into the cache specified by cacheName
  public void put(String cacheName, List<CacheableObject> objects) {
    try {
      this.redisTemplate.executePipelined(new RedisCallback<Object>() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
          for(CacheableObject object: objects) {
            redisTemplate.opsForHash().put(cacheName, object.getKey(), object.getValue()); 
          }
          return null;
        }
      });
    }
    catch(Exception e) {
        log.error("Error inserting objects into Redis cache: {}", e.getMessage());
    }
}

RedisTemplate itself is configured using a configuration class such as the following: RedisTemplate 本身是使用如下配置类配置的:

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport implements 
                                                               CachingConfigurer {

  @Value("${redis.hostname}")
  private String redisHost;
  @Value("${redis.port}")
  private int redisPort;
  @Value("${redis.timeout.secs:1}")
  private int redisTimeoutInSecs;
  @Value("${redis.socket.timeout.secs:1}")
  private int redisSocketTimeoutInSecs;
  @Value("${redis.ttl.hours:1}")
  private int redisDataTTL;

  @Bean
  JedisConnectionFactory jedisConnectionFactory() {
     RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
     return new JedisConnectionFactory(redisStandaloneConfiguration);
  }
 
  @Bean
  public RedisTemplate<Object, Object> redisTemplate() {
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
    redisTemplate.setConnectionFactory(jedisConnectionFactory());
    return redisTemplate;
}   

  @Bean
  public RedisCacheManager redisCacheManager (JedisConnectionFactory jedisConnectionFactory) {
    RedisCacheConfiguration redisCacheConfiguration = 
            RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues()
            .entryTtl(Duration.ofHours(redisDataTTL)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.java()));
    redisCacheConfiguration.usePrefix();
    RedisCacheManager redisCacheManager = 
            RedisCacheManager.RedisCacheManagerBuilder.
            fromConnectionFactory(jedisConnectionFactory)
            .cacheDefaults(redisCacheConfiguration).build();
    redisCacheManager.setTransactionAware(true);
    return redisCacheManager;
}

  @Bean
  public JedisPoolConfig poolConfig() {
    final JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    jedisPoolConfig.setTestOnBorrow(true);
    jedisPoolConfig.setMaxTotal(100);
    jedisPoolConfig.setMaxIdle(100);
    jedisPoolConfig.setMinIdle(10);
    jedisPoolConfig.setTestOnReturn(true);
    jedisPoolConfig.setTestWhileIdle(true);
    return jedisPoolConfig;
}

  @Override
  public CacheErrorHandler errorHandler() {
    return new RedisCacheErrorHandler();
  }
}

Thanks for the clear explanation, I have one doubt here canu please clarify, does it create only one connection or multiple connections with executepipeline?感谢您的明确解释,我有一个疑问,请澄清一下,它是只创建一个连接还是使用executepipeline创建多个连接? And if i want to just use below for for loop without executepipeline then how it handles the connections.如果我只想在没有执行管道的情况下使用下面的 for 循环,那么它如何处理连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM