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();
        }
    }
}

 

  

上一篇:Ling to sql 多表查询,多个条件进行关联


下一篇:组合数奇技淫巧