zoukankan      html  css  js  c++  java
  • Redis有序Set、无序Set的使用经历

      为了实现一个类似关系数据库中的卖家信息的单表,首先我们知道单表必然可增删查改,其次为了区分先来后到又需要有ID主键且自增长。开始考虑使用hash数据类型,因为hash是key+列1、列2...这样一来跟关系型数据库的数据模型是最像的,但满足不了第二点。所以后来考虑使用有序set,将各列作为属性封装到一个对象中,通过json序列化为String作为有序set的value。key是固定的,我们只能对有序set整体设置失效时间,无法单独针对具体元素设置失效时间。score均为自增长的序列,score是有序set之所以有序的原因。为了解决最后一个问题,自增长的主键我们另外用一个key来维护,利用redis的incr命令来实现自增长。

      上面的有序set中维护的是多个卖家的信息,而每个卖家会维护一系列订单ID列表,这样我们就能快速的根据订单ID定位到是哪个卖家了。这次没有顺序要求,当然订单是不能重复的,所以我选择无序set。废话不多说,直接看例子:

    package com.crocodile.springboot.redis;
    
    import com.crocodile.springboot.model.Merchant;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    import java.io.IOException;
    import java.util.*;
    
    @Component
    public class JedisOperation {
    
        // redis缓存Sorted Set的key
        private final static String REDIS_SORT_KEY = "merchant_sorted_set";
    
        // json对象映射
        private ObjectMapper om = new ObjectMapper();
    
        @Autowired
        private JedisPool jedisPool;
    
       // 读取applicantion中的redis相关配置项  
       @Bean
        @ConfigurationProperties("redis")
        public JedisPoolConfig jedisPoolConfig() {
            return new JedisPoolConfig();
        }
    
        // Jedis的实例池,从配置项的redis.host中读取redis的ip地址
        @Bean(destroyMethod = "close")
        public JedisPool jedisPool(@Value("${redis.host}") String host) {
            return new JedisPool(jedisPoolConfig(), host);
        }

    /** * 加入无序set,下面已设置了无序set的失效时间,在此之后加入不影响原有失效时间 * @param key * @param orders */ public void addOrdersPerHour(String key, List<Order> orders) { try (Jedis jedis = jedisPool.getResource()) { orders.forEach(order -> { try { jedis.sadd(key, order.getOrderId()); } catch (Exception e) { } }); } } /** * 遍历订单列表,放入无序set,一个月后该无序set中全部元素均失效 * @param key * @param orders */ public void addOrdersPerMonth(String key, List<Order> orders) { try (Jedis jedis = jedisPool.getResource()) { jedis.expire(key, 60 * 60 * 24 * 30); orders.forEach(order -> { try { jedis.sadd(key, order.getOrderId()); } catch (Exception e) { } }); } } /** * 获取总记录数 * * @return */ public int getCounts() { int count; try (Jedis jedis = jedisPool.getResource()) { count = Integer.valueOf(String.valueOf(jedis.zcard(REDIS_SORT_KEY))); } return count; } /** * 根据起始索引、结束索引查询有序set * * @param start * @param end * @return */ public List<Merchant> getDatas(int start, int end) { List<Merchant> merchants = new ArrayList<>(); try (Jedis jedis = jedisPool.getResource()) { Set<String> keys = jedis.zrange(REDIS_SORT_KEY, start, end); keys.forEach(merchantStr -> { Merchant merchant = null; try { merchant = om.readValue(merchantStr, Merchant.class); } catch (IOException e) { } if (merchant != null) { merchants.add(merchant); } }); } return merchants; } /** * 根据score(维护key为id的自增序列)添加到有序Set * * @param merchant */ public void addMerchant(Merchant merchant) { try (Jedis jedis = jedisPool.getResource()) { Long sequence = jedis.incr("id"); merchant.setId(sequence); String merchantStr = om.writeValueAsString(merchant); jedis.zadd(REDIS_SORT_KEY, sequence, merchantStr); } catch (Exception e) { return e.getMessage(); } } /** * 根据score修改有序set中的数据,先删后增 * * @param merchant */ public void modifyMerchant(Merchant merchant) { try (Jedis jedis = jedisPool.getResource()) { String merchantStr = om.writeValueAsString(merchant); jedis.zremrangeByScore(REDIS_SORT_KEY, merchant.getId(), merchant.getId()); jedis.zadd(REDIS_SORT_KEY, merchant.getId(), merchantStr); } catch (Exception e) { return e.getMessage(); } } /** * 根据score删除有序set中的数据 * * @param id * @return */ public void delMerchant(String id) { try (Jedis jedis = jedisPool.getResource()) { jedis.zremrangeByScore(REDIS_SORT_KEY, Double.valueOf(id), Double.valueOf(id)); } catch (Exception e) { return e.getMessage(); } } }

    public Merchant queryMerchantIdByOrderId(String orderId, List<Merchant> merchants) {
    Merchant merchant = null;
    try (Jedis jedis = jedisPool.getResource()) {
    Iterator<Merchant> iter = merchants.iterator();
    while (iter.hasNext()) {
    Merchant merchantTemp = iter.next();
    if (jedis.sismember(merchantTemp.getMerchantId(), orderId)) {
    merchant = merchantTemp;
    break;
    }
    }
    }
    return merchant;
    }
     

       applicantion.properties配置文件很简单:

    #Redis数据库配置
    redis.host=localhost
    redis.maxTotal=5
    redis.maxIdle=5
    redis.testOnBorrow=true

      这里没有配置端口,jedis将默认设置端口为6379。再看下redis客户端下的有序set和无序set的操作:

    127.0.0.1:6379> incr id
    (integer) 1
    127.0.0.1:6379> get id
    "1"
    127.0.0.1:6379> zadd set_key 1 merchantId_1
    (integer) 1
    127.0.0.1:6379> incr id
    (integer) 2
    127.0.0.1:6379> get id
    "2"
    127.0.0.1:6379> zadd set key 2 merchantId_2
    (error) ERR syntax error
    127.0.0.1:6379> zadd set_key 2 merchantId_2
    (integer) 1
    127.0.0.1:6379> zcard set_key
    (integer) 2
    127.0.0.1:6379> zrange set_key 0 -1
    1) "merchantId_1"
    2) "merchantId_2"
    127.0.0.1:6379> zremrangebyscore set_key 2 2
    (integer) 1
    127.0.0.1:6379> zrange set_key 0 -1
    1) "merchantId_1"
    127.0.0.1:6379> sadd merchantId_1 merchantInfo
    (integer) 1
    127.0.0.1:6379> expire merchantId_1 60
    (integer) 1
    127.0.0.1:6379> ttl merchantId_1
    (integer) 53
    127.0.0.1:6379> smembers merchantId_1
    1) "merchantInfo"
    127.0.0.1:6379> sismember merchantId_1 merchantInfo
    (integer) 1
    127.0.0.1:6379>

      

  • 相关阅读:
    【ARTS】打卡第七周
    【ARTS】打卡第六周
    【ARTS】打卡第五周
    【leetcode】 438. Find All Anagrams in a String
    【ARTS】打卡第四周
    【ARTS】打卡第三周
    【leetcode】 11. Container With Most Water
    【ARTS】打卡第二周
    【ARTS】打卡第一周
    深度VS广度——谈谈对测试职业的一些思考
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/10805994.html
Copyright © 2011-2022 走看看