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>

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM