非自增编号字段,避免生成重复编号(以pdfNo编号为例)RedisLock/ReadLock
非自增编号字段,避免生成重复编号(以pdfNo编号为例)
有个场景,用户查询延误航班信息,然后生产一个编号,默认第一个编号是1000001,其后新增的编号默认自增加1。每次有人来查延误信息,如果延误信息存在,则取查询数据库pdfNo字段,查询最大的编号,然后+1后,再插入一条新的延误记录。这样会造成多人同时查询,并生成延误记录是,pdfNo的编号会重复现象。
经过分析,俺们组长说,有2中多种解决方案,一种是分布式锁方案,一种是insert into select from方案,一种是RedisLock方案。
本人愚笨,说下insert into select from, 和 RedisLock方案
insert into select from:
在入库的时候,查询下最大pdfNo,然后加一入库
方法一:
INSERT INTO Websites (name, country)
SELECT app_name, country FROM apps
WHERE id=1;

二:
表结构如上图
insert into test_aaa (title, pdfno) select "hello", max(pdfno) +1 as pdfmax from test_aaa;
RedisLock方法
VariableKeyLock.java
import java.util.concurrent.locks.Lock; /**
* 可变key锁
*
* @author zhangyang-b
*/
public interface VariableKeyLock extends Lock { boolean tryLock(String key); void lock(String key); void unlock(String key);
}
RedisLock.java
public class RedisLock implements VariableKeyLock {
public static final String LOCK = "LOCK";
@Autowired
private RedisConnectionFactory factory;
private ThreadLocal<String> localValue = new ThreadLocal<String>();
/**
* 解锁lua脚本
*/
private static final String UNLOCK_LUA =
"if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";
@Override
public void lock() {
if (!tryLock()) {
try {
Thread.sleep(new Random().nextInt(10) + 1);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
}
lock();
}
}
@Override
public void lock(String key) {
if (!tryLock(key)) {
try {
Thread.sleep(new Random().nextInt(10) + 1);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
}
lock(key);
}
}
@Override
public boolean tryLock() {
RedisConnection connection = null;
try {
connection = factory.getConnection();
Jedis jedis = (Jedis)connection.getNativeConnection();
String value = UUID.randomUUID().toString();
localValue.set(value);
String ret = jedis.set(LOCK, value, "NX", "PX", 10000);
return ret != null && "OK".equals(ret);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (connection != null) {
connection.close();
}
}
return false;
}
@Override
public boolean tryLock(String key) {
RedisConnection connection = null;
try {
connection = factory.getConnection();
Jedis jedis = (Jedis)connection.getNativeConnection();
String value = UUID.randomUUID().toString();
localValue.set(value);
String ret = jedis.set(key, value, "NX", "PX", 10000);
return ret != null && "OK".equals(ret);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (connection != null) {
connection.close();
}
}
return false;
}
@Override
public void unlock() {
String script = UNLOCK_LUA;
RedisConnection connection = null;
try {
connection = factory.getConnection();
Object jedis = connection.getNativeConnection();
if (jedis instanceof Jedis) {
((Jedis)jedis).eval(script, Arrays.asList(LOCK), Arrays.asList(localValue.get()));
} else if (jedis instanceof JedisCluster) {
((JedisCluster)jedis).eval(script, Arrays.asList(LOCK), Arrays.asList(localValue.get()));
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public void unlock(String key) {
String script = UNLOCK_LUA;
RedisConnection connection = null;
try {
connection = factory.getConnection();
Object jedis = connection.getNativeConnection();
if (jedis instanceof Jedis) {
((Jedis)jedis).eval(script, Arrays.asList(key), Arrays.asList(localValue.get()));
} else if (jedis instanceof JedisCluster) {
((JedisCluster)jedis).eval(script, Arrays.asList(key), Arrays.asList(localValue.get()));
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (connection != null) {
connection.close();
}
}
}
}
用法:
redisLock.lock(key名);
try{
int maxPdfNo = 0;
try{
maxPdfNo = flightDelayPdfJService.queryMaxPdfNo();
}catch (Exception e){
e.printStackTrace();
}
if(maxPdfNo > 0){
return maxPdfNo + 1;
}else{
return 1000001;
}
}finally {
redisLock.unlock(key名);
}
非自增编号字段,避免生成重复编号(以pdfNo编号为例)RedisLock/ReadLock的更多相关文章
- 编写Java程序,模拟网上商城购物,当用户选好物品提交订单时,每笔订单会自动生成一个唯一的订单编号。
查看本章节 查看作业目录 需求说明: 模拟网上商城购物,当用户选好物品提交订单时,每笔订单会自动生成一个唯一的订单编号.而部分电子商务网站在数据高峰期时,一毫秒可能需要处理近千笔的订单 现在简单模拟 ...
- Dynamics CRM EntityCollection 根据实体中的某个字段为依据去除重复数据
CRM中通过QueryExpression查询出了一个EntityCollection集,但有时会存在重复数据,QueryExpression中有个属性distinct,只要设置为true就能过滤 ...
- SQL语句 删除表user 中字段name 内容重复的记录,
public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...
- 解决MybatisGenerator多次运行mapper生成重复内容
MybatisGenerator插件是Mybatis官方提供的,这个插件存在一个固有的Bug,即当第一次生成了Mapper.xml之后,再次运行会导致Mapper.xml生成重复内容,而影响正常的运行 ...
- php 之根据mysql字段 批量生成 array 数组
ci框架 验证字段 需要 生成类似为: array('field' => 'admin_id','label' => '账号ID','rules' => 'integer'), ...
- C#:lock锁与订单号(或交易号)的生成
在弄电商类网站的时候,往往是根据年月日时分秒的格式生成订单号(yyyyMMddHHmmss),为了解决并发性,就直接在生成订单号的区域块加上lock. 下面,我们来简单测试一下. 1.新建项目(控制台 ...
- Spring boot redis自增编号控制 踩坑
近段期间,公司 接手一个订单号生成服务,规则的话已经由项目经理他们规定好了,主要是后面的四位数代表的关于当前订单号已经执行第几个了.而这里面有一个要求就是支持分布式.为了实现这个东西,刚开始我使用了r ...
- s验证数据库中字段值是否重复
daoImpl: public String isVipCode(String vipcode) { String sql = "from FfzjUserEntity where vip_ ...
- php生成员工编号,产品编号
由于某些原因需要获取数据库最大的id值.所以出现了这段php 获取数据库最大的id代码了.这里面的max(id) 这里面的id 就是要获取最大的id了.如果是别的字段请填写为其他字段 获取数据库中最大 ...
随机推荐
- ContainsExtensions不分区大小写
public static class ContainsExtensions { public static bool Contains(this string source, string valu ...
- Windows的socket编程
################服务端 1.准备工作导入头文件 #include<WinSock2.h> #pragma comment(lib, "ws2_32.lib&quo ...
- Oracle 11g Java驱动包ojdbc6.jar安装到maven库,并查看jar具体版本号
ojdbc6.jar下载 Oracle官方宣布的Oracle数据库11g的驱动jar包是ojdbc6.jar ojdbc6.jar下载地址:https://www.oracle.com/technet ...
- golang --iota 用法
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" ...
- RAC环境备份,RMAN异机在单实例环境恢复redo问题
目的:客户环境11.2.0.4 ,多节点RAC环境,现在使用带库的备份,在单机环境测试备份有效性 1.normal参数文件 删除集群相关参数cluster 2.mount 使用备份的控制文件进行还原 ...
- Harbor仓库配置https访问
注:高版本(14以上)docker执行login命令,默认使用https,且harbor必须使用域名,只是用ip访问是不行的. 假设使用的网址是:www.harbor.mobi,本机ip是192.16 ...
- Oracle——无法在查询中执行 DML 操作
今天在调用Oracle Function遇到一个异常
- 和我一起,重零开始学习Ant Design Pro开发解决方案(一)安装开发环境
安装NODEJS 什么是NODEJS? 百度一下吧,这个真不知道,老码农,别笑话我: 简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome Jav ...
- opencv 源码分析 CUDA可分离滤波器设计 ( 发现OpenCV的cuda真TM慢 )
1. 主函数 void SeparableLinearFilter::apply(InputArray _src, OutputArray _dst, Stream& _stream) { G ...
- [转].net mvc + vuejs 的项目结构
.net项目结构: 程序目录结构: vue操作: 前提:安装npm ,vue,vue-cli 1.进入控制台窗口 2.进入程序目录 3.运行 vue init webpack webjs 生成webj ...