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:> 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的使用经历的更多相关文章
- 四:redis的sets类型 - 相关操作(有序和无序集合)
================四十五种(有序和无序集合):sets种类(它是一个集)============= 简介: set它代表的集合.加入是随意添加----->无序集合 ...
- Redis 有序集合(sorted set),发布订阅,事务,脚本,连接,服务器(三)
Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...
- Redis 有序集合(sorted set)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过分数来为集合中的成员进行从小到大的排序. 有序 ...
- Java设置PDF有序、无序列表
文档中的设置有序或无序列表是一种反应内容上下级关系或者内容相同属性的方式,与单纯的文字叙述相比,它能有效增强文档内容的条理性,突出重点.因此,本文将分享通过Java编程在PDF文档中设置有序或无序列表 ...
- redis 有序集合(zset)函数
redis 有序集合(zset)函数 zAdd 命令/方法/函数 Adds the specified member with a given score to the sorted set stor ...
- Redis有序集合
Redis有序集合类似Redis集合存储在设定值唯一性.不同的是,一个有序集合的每个成员带有分数,用于以便采取有序set命令,从最小的到最大的分数有关. Redis 有序set添加,删除和测试中的O( ...
- Redis 有序聚合实现排行榜功能
排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择.Redis有序集合非常适用于有序不重复数据的存储 一般排行榜都是有实效性的,比如“用户积分榜”.如果没有实 ...
- redis有序集合的使用
Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...
- redis有序集合数据类型---sortedset
一.概述 redis有序集合和集合一样,也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数. redis正式通过分数来为集合中的重圆进行从小到大的 ...
- 数据结构与算法简记--redis有序集合实现-跳跃表
跳表 定义 为一个值有序的链表建立多级索引,比如每2个节点提取一个节点到上一级,我们把抽出来的那一级叫做索引或索引层.如下图所示,其中down表示down指针,指向下一级节点.以此类推,对于节点数为n ...
随机推荐
- 13 Windows编程——系统内置窗口子类型之静态子窗口
静态子窗口类型 wndclass:static 源码 #include<Windows.h> #include<Windowsx.h> HINSTANCE G_h; LRESU ...
- 虚拟机ipv6环境搭建操作指南
一.vmware的相关配置 (1)点击编辑,选择虚拟网络编辑器 (2)选择带NAT模式的VMnet8网络,点击NAT设置 (3)在NAT设置中启用IPV6 (4)设置好后,点击应用 (5)再选择镜 ...
- 搭建一个jumpserver跳板机
1,部署jumpserver 建立阿里云公网源yum仓库 清除缓存重新建立缓存 ip后面直接回车,下面输入y 地址端口账户密码直接回车 ,询问跳过输入y,是否继续输入y 用户名回车,输入自己要设置的密 ...
- 版本问题---cuda和tensorflow的版本对应关系
cuda和tensorflow的版本有对应关系 https://tensorflow.google.cn/install/source#linux
- python 学习笔记_2 模拟socket编程 服务端、客户端通信(参考核心编程2代码实现)
服务器端代码实现: #!/usr/bin/env python#coding=gbk'''接收客户端字符串,在字段串前面打上当前时间,然后返回server端采用 python2 linux下调试运行客 ...
- 《图解HTTP》笔记1
Web 是建立在 HTTP 协议上通信的. HTTP 通常被译为超文本传输协议,但这种译法并不严谨.严谨的译名应该为“超文本转移协议”. 通过发送请求获取服务器资源的 Web 浏览器等,都可称为客户端 ...
- 一步步来用C语言来写python扩展
本文介绍如何用 C 语言来扩展 python.所举的例子是,为 python 添加一个设置字符串到 windows 的剪切板(Clipboard)的功能.我在写... 本文介绍如何用 C 语言来扩展 ...
- 001_UCOSIII引入原因
(一)在前年的学习中一直都是在裸机上跑程序的,根本没有用到操作系统,但是因为以前开发的东西很小,根本用不着,也没必要在操作系统上跑,所以就没有学习.在未来的几天中将进军UCOSIII.为什么选择UCO ...
- Laravel API Errors and Exceptions: How to Return Responses
Laravel API Errors and Exceptions: How to Return Responses February 13, 2019 API-based projects are ...
- LibreOJ #119. 最短路
二次联通门 : LibreOJ #119. 最短路 /* LibreOJ #119. 最短路 堆优化的Dijkstra */ #include <cstring> #include < ...