为了实现一个类似关系数据库中的卖家信息的单表,首先我们知道单表必然可增删查改,其次为了区分先来后到又需要有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:> incr id
(integer)
127.0.0.1:> get id
""
127.0.0.1:> zadd set_key merchantId_1
(integer)
127.0.0.1:> incr id
(integer)
127.0.0.1:> get id
""
127.0.0.1:> zadd set key merchantId_2
(error) ERR syntax error
127.0.0.1:> zadd set_key merchantId_2
(integer)
127.0.0.1:> zcard set_key
(integer)
127.0.0.1:> zrange set_key -
) "merchantId_1"
) "merchantId_2"
127.0.0.1:> zremrangebyscore set_key
(integer)
127.0.0.1:> zrange set_key -
) "merchantId_1"
127.0.0.1:> sadd merchantId_1 merchantInfo
(integer)
127.0.0.1:> expire merchantId_1
(integer)
127.0.0.1:> ttl merchantId_1
(integer)
127.0.0.1:> smembers merchantId_1
) "merchantInfo"
127.0.0.1:> sismember merchantId_1 merchantInfo
(integer)
127.0.0.1:>

  

Redis有序Set、无序Set的使用经历的更多相关文章

  1. 四:redis的sets类型 - 相关操作(有序和无序集合)

    ================四十五种(有序和无序集合):sets种类(它是一个集)=============      简介:  set它代表的集合.加入是随意添加----->无序集合    ...

  2. Redis 有序集合(sorted set),发布订阅,事务,脚本,连接,服务器(三)

    Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...

  3. Redis 有序集合(sorted set)

    Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过分数来为集合中的成员进行从小到大的排序. 有序 ...

  4. Java设置PDF有序、无序列表

    文档中的设置有序或无序列表是一种反应内容上下级关系或者内容相同属性的方式,与单纯的文字叙述相比,它能有效增强文档内容的条理性,突出重点.因此,本文将分享通过Java编程在PDF文档中设置有序或无序列表 ...

  5. redis 有序集合(zset)函数

    redis 有序集合(zset)函数 zAdd 命令/方法/函数 Adds the specified member with a given score to the sorted set stor ...

  6. Redis有序集合

    Redis有序集合类似Redis集合存储在设定值唯一性.不同的是,一个有序集合的每个成员带有分数,用于以便采取有序set命令,从最小的到最大的分数有关. Redis 有序set添加,删除和测试中的O( ...

  7. Redis 有序聚合实现排行榜功能

    排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择.Redis有序集合非常适用于有序不重复数据的存储 一般排行榜都是有实效性的,比如“用户积分榜”.如果没有实 ...

  8. redis有序集合的使用

    Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...

  9. redis有序集合数据类型---sortedset

    一.概述 redis有序集合和集合一样,也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数. redis正式通过分数来为集合中的重圆进行从小到大的 ...

  10. 数据结构与算法简记--redis有序集合实现-跳跃表

    跳表 定义 为一个值有序的链表建立多级索引,比如每2个节点提取一个节点到上一级,我们把抽出来的那一级叫做索引或索引层.如下图所示,其中down表示down指针,指向下一级节点.以此类推,对于节点数为n ...

随机推荐

  1. Django权限和认证模块的解读

    from rest_framework.views import APIView 找到APIView中的dispatch方法 class MyAuth: def authenticate(self): ...

  2. 7.MapReduce操作Hbase

    7 HBase的MapReduce   HBase中Table和Region的关系,有些类似HDFS中File和Block的关系.由于HBase提供了配套的与MapReduce进行交互的API如 Ta ...

  3. OpenCV读取图像问题:OpenCV(3.4.3) D:\Build\OpenCV\opencv-size.width0 && size.height0 in function 'cvimshow'

    版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/83280067 - 问题与解决 最近正在学OpenCV,发现 ...

  4. idou老师教你学Istio 29:Envoy启动流程

    1. 功能概述 Envoy启动时,会启动一个进程,并在这个进程中启动很多线程,这样,可以启动很多worker线程,一般worker线程数与核心数相同,每个worker线程处理所有已配置的listene ...

  5. Thinkphp 两级联动

    <!-- 前端代码部分--><div class="pop-movegroup" id="salesmanBox"> <dl> ...

  6. Junit加载Spring容器作单元测试

    阅读目录 > 基本的搭建 > 常见的用法 如果我们需要对我们的Service方法作单元测试,恰好又是用Spring作为IOC容器的,我们可以这么配置Junit加载Spring容器,方便做单 ...

  7. spring 定时任务的 执行时间设置规则-----看完这篇就懂了

    单纯针对时间的设置规则 org.springframework.scheduling.quartz.CronTriggerBean允许你更精确地控制任务的运行时间,只需要设置其cronExpressi ...

  8. learning express step(十二)

    learning express view engine function const express = require('express'); const app = express(); app ...

  9. 威尔逊定理x

    威尔逊定理 在初等数论中,威尔逊定理给出了判定一个自然数是否为素数的充分必要条件.即:当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p ),但是由于阶乘是呈爆炸增长的,其结论对于实际操 ...

  10. Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数

    Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...