问题是这个亚子的,故事啊不对,是事故发生在大半年前,本人是一名微信企业号Java开发程序猿,写了一个上报业绩的小页面,然后把数据汇总一下做个报表。很简单一个小网页。写完之后,最开始用的“微信企业号开发者工具”做的测试,从开始写到最后测试都没问题,但是测上线的候,就 暴漏出问了,我明明只点了一次提交按钮,但是最后存到数据库里数据竟然有两条。
懵了,我手快?点了两次?咋回事,问了前台小哥,
你按钮样式是自己写的吗。
不是,用框架写的。
那你加一个框啥的,手快的像能点两次。
10分钟后。加完了。测试。。。。。
偶尔还是会出这种问题。
继续懵比。
页面加了vconsole。ajax就一次。怎么可能存进去两次。
在懵比(百度)了一上午之后, 发现这种狗问题可能是微信的x5内核的浏览器的问题。其他 大佬对这个问题是这么解释的:
我觉得是csdn的问题,我的光标一直在 乱跑,不行我去记事本里写了 ,然后复制过来8。
微信你这样乱发请求经过我的同意了吗?
热心网友A出招:“这问题简单,你只要在url上加一个参数,叫&connect_redirect=1 ,就行了”
发现救命稻草之后,马上抓住,试了一下。发现,这稻草,不行啊,加了之后还是调起了两次啊。
没办法项目马上上线了。只能找野路子了。
这时候公司内另一个程序猿出招:“就一个insert又不会失败,你就先给他返回个成功,然后在建个线程去存不就完了。”
好主意啊。马上搞,直接写返回语句。结果别说 还真成功了。
所以就这样写的:
Thread t1 = getThread("1",platform,response);
t1.start();
json.put("state", "success");
json.put("keyId", paltform.getKeyId());
response.getWriter().println(json);
就这样安安心心的上线了大半年之后。直到上个月,原本安稳的生活,因为一个功能,变得稀烂。
老大说有个需求,就是把我上报的数据,通过接口推到另一个系统里。就叫那个系统为c系统吧。
没问题,简单点一批。给我个接口,写个json调一下不就完事了吗。
还是一样的配方,还是一样的错误。
我点一次推送,他那边收到了两条数据。
懵比。因为推送和直接insert不一样,他是有很大几率推送失败的。原因可能是,用户填写的时候,某些数据填写不完整,或者两个平台数据不统一。反正不成功的概率很大。不能直接返回成功。
不能这么搞了。只能继续想(查)办(百)法(度)了。
查了两天之后,毫无进展。这时。我们的高级开发工程师可能是看到了我发际线猛地往后移了一截。然后来问我怎么回事。
给他解释了一番。高级开发工程师给我出了这么个招子。
不得不说,不愧是高级开发工程师。思路就是不一样。路子够野。
马上搞了一套,用redis写的缓存。但是我没有写时间戳(懒)。直接用的keyid做的key,结果数据是只有一条了。
但是
前台接不到反馈结果了。
这不行啊,客户们不就认为他一直没有推送成功吗。
又经过了一顿思(百)考(度)了解到。
结果代码是这样的:
Jedis redis = new Jedis("ip地址",6379);//生产环境
redis.auth("mima");
if(redis.exists(keyId)) {
int count=0;
while(redis.exists(keyId)) {
if(keyId.equals(redis.get(keyId))) {
Thread.sleep(100);
count++;
}else if("success".equals(redis.get(keyId))){
json.put("code", "success");
break;
}else if("failed".equals(redis.get(keyId))) {
json.put("code", "false");
break;
}
if(count>300) {
break;
}
}
response.getWriter().println(json);
}else {
redis.setex(keyId, 300,keyId);
//正常调接口要做的事情
if("true".equals(success)) {
//推送成功,更改状态,推送之后,isPush==>1,status==>2,已推送,审批通过状态
ipfs.changePushStatus(keyId);//更改状态
json.put("code", "success");
} else if("inexists".equals(success)) {
json.put("code", "inexists");
} else if("false".equals(success)) {
json.put("code", "false");
}
}
因为我最开始写的是第二次成功之后就马上把缓存删除了(怕占内存),然后就还会一直出这种问题。
所以我最后选择了一种比较懒的方法,写了一个缓存的存活时间,给了5分钟。就是说,同一单在5分钟之内不能重复推送。这样就不会出现推送重复的问题了。问题到现在就已经解决了。路子很野,不是正常思路。但是很有效。
如果看到这篇文章的小伙伴们,有更有效的方法,欢迎留言一起讨论一番。