非自增编号字段,避免生成重复编号(以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了.如果是别的字段请填写为其他字段 获取数据库中最大 ...
随机推荐
- java接入微信JS-SDK
在微信公众号开发中不可,jssdk的接入虽然不是必须,但是根据业务需求我们还是可能用到,下面是自己整理的关于java接入的jssdk的方法,这里是记录关于接入微信JS-SDK的准备工作,关于接入JS- ...
- Android--Google Map API V2使用
一.获取API Key 1.先获取SHA-1 fingerprint 数字证书是有两种,一种是debug,还有release.前者只能用于测试:后者才可以用于实际产品. debug:在命令行中输入命令 ...
- Educational Codeforces Round 66 (Rated for Div. 2)
A.直接模拟. #include<cstdio> #include<cstring> #include<iostream> #include<algorith ...
- delphi indy Idhttp error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version
在使用 indy 中的 idhttp 组件访问 https 网站时,出现如下错误: error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert pr ...
- WebApi接收接收日期格式参数时,日期类型(2019-10-08T16:00:00.000Z)后台接收时间少8小时问题
前端使用的是elementui的日期控件,将日期格式的数据提交到webapi后台时,接收到的日期格式少了8小时,这个原因是由于时区引起的,应该在WebApiConfig进行配置转成本地时间,解决少8小 ...
- aspnetcore 容器化部属到阿里云全过程记录
第一次写博客,作为一个全栈er,记录一下从阿里云到产品运维上线的全过程 一.阿里云上的设置 购买阿里云ECS后: 进控制台查看实例公网IP 在控制台.网络与安全->安全组,配置规则 点击进去可以 ...
- 转 js一个简单实用的弹出层
关闭 点击查看 >> <html> <head> <title>新文件标题</title> <script type=" ...
- 浅谈dubbo服务
Dubbo分布式服 推荐大家一个画图工具:https://www.processon.com/i/572d51efe4b0c3c74981ec14 1.Dubbo是一个分布式服务框架,致力于提供高性能 ...
- sqlite移植
编译 # tar xvf sqlite-3.6.16.tar.gz # cd sqlite-3.6.16 # ./configure # ./configure --host=arm-linux -- ...
- [C#(WinForm)]判断第一次启动程序
来源:https://bbs.csdn.net/topics/220023353/(10楼) 在判断窗口上添加: string strIsFirstRun = "false"; b ...