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 ...
随机推荐
- httpd源码编译安装
什么是编译安装——编译:将源代码变为机器可执行的代码文件.安装:将可执行文件安装到操作系统里,才可以使用. 一.下载httpd源码包 在官网上下载httpd源码包http://httpd.apache ...
- 爬虫必备的web知识
爬虫定义.分类和流程 爬虫的定义: 网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序.爬虫就是模拟浏览器的行为,越像越好 ...
- 登录授权、TCP/IP、HTTPS
今天继续纯理论的东东,比较枯燥,但是又很重要,坚持.. 登录和授权 登录和授权的区别: 登录:身份认证,即确认「你是你」的过程. 授权:由身份或持有的令牌确认享有某些权限(例如获取用户信息).登录过程 ...
- jpa 如果返回java对象,会自动更新对象值(坑!!)
//上一段示例代码List<Member> memberList = memberDao.findByLoginNameIn(names);for (Member m : memberLi ...
- python_tkinter事件
1.事件绑定函数(3个) 组件.bind('事件类型',事件函数) 为一个组件绑定一个操作 组件.bind_class('组件类型','事件类型',事件函数) 为一个类组件绑定一个操作 组件.bind ...
- JQuery中 text()、html() 以及 val()以及innerText、innerHTML和value
设置内容 - text().html() 以及 val() 我们将使用前一章中的三个相同的方法来设置内容: text() - 设置或返回所选元素的文本内容 html() - 设置或返回所选元素的内容( ...
- tableviewer自动调整列宽
public void resizeTableColumn(TableColumn[] treeColumns) { for (TableColumn tc : treeColumns) tc.pac ...
- docker harbor 清理释放存储空间
0.harbor界面端清理镜像 1.停止docker harbor docker-compose stop 2.预览运行效果 docker run -it --name gc --rm --volum ...
- Codeforces Round #585 (Div. 2) D. Ticket Game
链接: https://codeforces.com/contest/1215/problem/D 题意: Monocarp and Bicarp live in Berland, where eve ...
- python--openCV--鼠标事件
import cv2 import numpy as np cv2.namedWindow("new") def drawxxx(event,x,y,flags,param): # ...