非自增编号字段,避免生成重复编号(以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的更多相关文章

  1. 编写Java程序,模拟网上商城购物,当用户选好物品提交订单时,每笔订单会自动生成一个唯一的订单编号。

    查看本章节 查看作业目录 需求说明: 模拟网上商城购物,当用户选好物品提交订单时,每笔订单会自动生成一个唯一的订单编号.而部分电子商务网站在数据高峰期时,一毫秒可能需要处理近千笔的订单 现在简单模拟 ...

  2. Dynamics CRM EntityCollection 根据实体中的某个字段为依据去除重复数据

    CRM中通过QueryExpression查询出了一个EntityCollection集,但有时会存在重复数据,QueryExpression中有个属性distinct,只要设置为true就能过滤 ...

  3. SQL语句 删除表user 中字段name 内容重复的记录,

    public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...

  4. 解决MybatisGenerator多次运行mapper生成重复内容

    MybatisGenerator插件是Mybatis官方提供的,这个插件存在一个固有的Bug,即当第一次生成了Mapper.xml之后,再次运行会导致Mapper.xml生成重复内容,而影响正常的运行 ...

  5. php 之根据mysql字段 批量生成 array 数组

    ci框架 验证字段 需要 生成类似为: array('field' => 'admin_id','label' => '账号ID','rules' => 'integer'),    ...

  6. C#:lock锁与订单号(或交易号)的生成

    在弄电商类网站的时候,往往是根据年月日时分秒的格式生成订单号(yyyyMMddHHmmss),为了解决并发性,就直接在生成订单号的区域块加上lock. 下面,我们来简单测试一下. 1.新建项目(控制台 ...

  7. Spring boot redis自增编号控制 踩坑

    近段期间,公司 接手一个订单号生成服务,规则的话已经由项目经理他们规定好了,主要是后面的四位数代表的关于当前订单号已经执行第几个了.而这里面有一个要求就是支持分布式.为了实现这个东西,刚开始我使用了r ...

  8. s验证数据库中字段值是否重复

    daoImpl: public String isVipCode(String vipcode) { String sql = "from FfzjUserEntity where vip_ ...

  9. php生成员工编号,产品编号

    由于某些原因需要获取数据库最大的id值.所以出现了这段php 获取数据库最大的id代码了.这里面的max(id) 这里面的id 就是要获取最大的id了.如果是别的字段请填写为其他字段 获取数据库中最大 ...

随机推荐

  1. Response知识点小结

    HTTP协议: 1. 响应消息:服务器端发送给客户端的数据 * 数据格式: 1. 响应行 1. 组成:协议/版本 响应状态码 状态码描述 2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状 ...

  2. 高仿linux下的ls -l命令——C语言实现

    主要用到的函数可以参考头文件,仅仅支持ls -l这功能,扩展就交给大家了0.0 相关测试图片: ​ ​ 话不多说,直接上码 #include <stdio.h> #include < ...

  3. 面试题:在一个文件中有 10G 个整数,乱序排列,要求找出中位数(内存限制为2G)

    假设整数为32bit,4个字节存储 这种题目,首先想到的是分而治之.将文件中数字分组.然后遍历文件中的数字,按分组进行计数.最后找到中位数所在的分组区间 1.如果10G个整数都为同一个,那么10G整数 ...

  4. C# CheckBoxList绑定值,设置及获取

    前端页面:.aspx <asp:CheckBoxList ID="ckbdot" runat="server" RepeatDirection=" ...

  5. 11.15java实习生面试总结

    坐了两个小时的车,到了面试地点面了十五分钟左右就结束了,心里有一点难受,不过这也是刚开始,后面的路还长着呢,所以先把面试官问的题目记录下来. 1.C语言能否跨平台? 虽然我面的是java实习生,但是因 ...

  6. Java 面向对象知识扩展

    四种权限修饰符 java有四种权限修饰符:public > protected > (default) > private   public protected default pr ...

  7. 浅析JavaScript异步

    一直以来都知道JavaScript是一门单线程语言,在笔试过程中不断的遇到一些输出结果的问题,考量的是对异步编程掌握情况.一般被问到异步的时候脑子里第一反应就是Ajax,setTimseout...这 ...

  8. Vue通过WebSocket建立长连接

    使用场景: 在项目开发中,后端需要处理一连串的逻辑,或者等待第三方的数据返回来进行处理之后在返回给前端,可能时间会很长,而且前端也不知道后端什么时候能处理好(时间长的话会达到10分钟左右),如果采用普 ...

  9. day33-python之多线程

    1.多线程实例 # import threading # import time # # import threading import time class MyThread(threading.T ...

  10. apk反编译工具包for Mac OS的使用

    在本文中我将介绍如何在Mac OS X上使用apktool.jar.dex2jar.jd-gui来进行apk的反编译和查看源码.下面会提供每个工具的下载地址. 测试环境:OS X EI Capitan ...