美文网首页Java高级交流
20180102-12问题整理

20180102-12问题整理

作者: 六月星空2011 | 来源:发表于2018-01-04 19:48 被阅读38次

    总摘要: spring


    2018-01-03

    • 摘要: spring注入对象
    1. 在springmvc获取request的方式中,RequestContextListener、.@Autowired,这两种会不会有并发时的线程安全问题?[河北-波涛]

    广州-小护士<-> 17:27:29
    controller注入request对象不会有并发问题
    河北-波涛(-) 17:34:27
    我也是在网上学习,想到这种问题,这两种方式的代码也没啥特殊的吧,如果我理解无误应该是:
    RequestContextListener:在web.xml配置lisener,在代码通过全局类获取(HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    @Autowired:
    就是什么request属性,实现spring自动注入吧
    @广州-小护士 注入式有啥特殊实现吗?不同方法对应不同request,而注入的是方法公用的类属性,这样不会并发时不会有问题,还是我对这两种方式的理解有误
    成都-梅小西(-) 17:42:17
    controller里注入的对象只是线程安全
    成都-勇<-> 17:46:12
    利用threadlocal 和 ObjectFactory来实现的线程安全,每次在processRequest设置的reqeust对象, 你看FrameworkServlet这个类里面的service()方法嘛
    广州-小护士<-> 17:51:22
    先看看 DispatchServlet源码~
    河北-波涛(-) 17:51:58
    a请求映射到controller的方法1,b请求映射到方法2,a、b都会对controller的request做注入,如果a、b请求同时发起,方法1和方法2中的去使用这个被注入的request,那这个被注入的request到底是对应哪个请求?这不会用线程安全问题?
    成都-勇<-> 17:54:05
    你可以简单的认为每个请求都会启一个线程来处理,所以threadlocal获取的对象也不一样的
    广州-小护士<-> 17:54:45
    如果说用到的request不是真实的request,是代理类. 从头到尾都在代理。注入request对象有两种方式嘛,一个是方法上传参,一个是字段注入. 方法传参很好理解,就是反射调用的时候传参进去, 字段注入就比较难理解了. 单例模式下也是安全的. Inject HttpServletRequest into Controller

    2018-01-08

    • 摘要: 线程阻塞
    1. 请教大家一个问题,我想限制一个线程池的最大队列不超过200,如果线程里已经有 core+队列200 个线程了,就阻塞,直到有线程空出来,才能放入新的线程请求, 有现成的线程池可以实现这样的功能吗?[杭州-Freedom]

    深圳-rubin(-) 13:59:44
    Jdk就可以满足呀
    杭州-Freedom(-) 14:00:30
    怎么做?
    广州-扬帆(-) 14:00:44
    线程池有四种方式来处理满了后的线程, 你如果满了后直接丢弃的话,本身就有的
    广州-小护士<-> 14:00:46
    @杭州-Freedom 你到底要队列还是线程池?
    北京-w(-) 14:01:25
    newFixedThreadPool
    杭州-Freedom(-) 14:02:18
    有点像队列+线程池,因为外部请求会一直不断的放入,但我想限制线程池最多只能有200个线程
    广州-小护士<-> 14:04:37
    我感觉你要的是生产者消费者模式,固定队列长度
    成都-孤狼(-) 14:04:40
    线程池不是有一个最大线程数目的参数么
    广州-小护士<-> 14:05:02
    PriorityBlockingQueue, DelayQueue, LinkedBlockingQueue, 我推荐的设计是用LinkedBlockingQueue + threadpool
    成都-梅小西(-) 14:30:54
    直接core=200然后用无限队列不就行了
    杭州-Freedom(-) 18:23:02
    最终解决方案: 支持生产阻塞的线程池

    2018-01-09

    • 摘要: 线程阻塞
    1. 下单支付遇到个问题, 下单后事务还没提交或者提交到数据库后还没执行完成,订单这边就收到付款成功的MQ 消息,但是此时根据结算号去查找订单的信息 有几率出现查询不到的场景,不知道有啥好办法规避掉呢? [杭州-水表哥]

    北京-喜<-> 17:26:10
    这个问题太多了啊. 都不知道该给你出什么方法了
    杭州-水表哥(-) 17:26:48
    我的问题吗?
    北京-喜<-> 17:27:03
    下单后事务还没提交或者提交到数据库后还没执行完成,订单这边就收到付款成功的MQ 消息 - 这里有2个问题
    北京-Sun(-) 17:27:07
    你这个是app端支付完成,但是你订单都没生成。
    北京-喜<-> 17:27:23
    此时根据结算号去查找订单的信息 有几率出现查询不到 - 这里是1个问题, 2, 你订单没生成或者没修改完状态对面就能付款了?
    湖南-stone(-) 17:27:29
    应该是先有订单吧,回调的时候再改状态啊, 怎么会查不到订单?这业务不正常吧
    杭州-水表哥(-) 17:28:02
    下单这边只是把订单号和结算信息返回给客户端,但是这个时候事务是已经提交到数据库了,但是量大的时候 其实数据库这个事务都还没执行完成, 会出现这种场景的 时间 基本精确到10毫秒以内
    北京-Sun(-) 17:28:37
    那就等事务完成后在返回给客户端啊。
    北京-喜<-> 17:29:10
    那就是业务流上 本身是保证不了时序的
    杭州-水表哥(-) 17:29:15
    这个事务完成后 其实也不可控啊,完全依赖数据库了
    北京-喜<-> 17:29:25
    你就需要额外做个 时序派发的处理, 面向状态机跃迁,自己做个统一的时序控制和排外处理
    杭州-水表哥(-) 17:30:12
    没看懂
    北京-喜<-> 17:30:15
    简单的说就是,支付回调回来,发现订单状态不对。先落地
    成都-奋斗(-) 17:30:18
    不是应该先把订单生成成功之后,再提交支付到第三方吗?
    重庆-Rocky(-) 17:30:26
    嗯 先存下来, 后期定时跑, 更新
    北京-喜<-> 17:30:41
    等订单下单成功之后,反向去解锁支付回调数据
    杭州-水表哥(-) 17:30:43
    @ffud 明白你的意思了,也就是所谓的补偿
    北京-喜<-> 17:30:52
    不是补偿, 你这个是前半段的技术设计有问题, 在后半段 谁也不知道互相之间的关系, 就得互相检测, 你完成的时候看看我对不对, 我完成到时候看看你在不在
    天津-Michael(-) 17:31:51
    下单和支付fork/join
    成都-奋斗(-) 17:32:04
    喜神,是不是应该先生成了订单,然后再提交到第三方支付,收到回调消息,更新库状态。这是才正常的业务流程吧, 怎么可能你自己的库的订单还未生成完成,第三方回调都来了
    北京-喜<-> 17:32:37
    是的,一般是这样, 否则有超卖、退款等风险
    重庆-Rocky(-) 17:32:55
    现在讨论的就是这种特殊情况
    杭州-水表哥(-) 17:33:21
    奋斗,我现在是订单号和结算号都生成了,事务也提交到数据库了,只是量大的场景下会出现事务还没执行完成,客户端就可以付款,订单这边就收到 MQ 消息了
    成都-奋斗(-) 17:33:36
    恩,明白你的意思, 你们是在订单事务里面也提交到第三方支付的吧
    杭州-水表哥(-) 17:34:13
    按照喜神的意思,我可以在收到 支付消息后 如果找不到订单信息的话 先落地后续再处理这笔单子
    北京-喜<-> 17:34:18
    就是状态机 跃迁不是 下单成功-> 支付成功,多了一个 支付成功->下单成功->支付成功, 应该是在事务里RPC了
    杭州-水表哥(-) 17:34:55
    我没在订单事务里面 提交第三方支付的
    北京-喜<-> 17:35:14
    有异步么
    杭州-水表哥(-) 17:35:19
    没异步的, 订单这边 只负责生产订单号和结算号, 客户端拿到这些数据后去请求支付
    北京-喜<-> 17:35:27
    没有的话,就是前面说的第3个问题 主从延迟, 订单有超时不支付,关闭的动作么?
    杭州-水表哥(-) 17:36:16
    有的, 我自己判断应该就是 事务提交到数据库里面 在排队等待处理,但是这边有结算号就可以去支付
    北京-喜<-> 17:36:39
    有好多方案可以处理,前面提到的可以, 还有一种是解决主从延迟的问题, 加热点,读主库也可以
    杭州-水表哥(-) 17:37:23
    目前订单和支付 我这边都是 读主库
    北京-Jerry(-) 17:36:38
    按照你说的应该会造成长款问题吧
    北京-喜<-> 17:37:37
    如果一直在读主库 出现这个问题
    杭州-水表哥(-) 17:37:39
    因为之前发生过主从延时 就没再读从库
    北京-喜<-> 17:37:42
    就是前面的设计的时序不对, 如果不改时序,就用先存储,后处理的方案
    杭州-水表哥(-) 17:38:07
    能详细的说下 哪里的时序不对吗?
    北京-Jerry(-) 17:38:08
    你的业务每秒多少笔交易?
    杭州-水表哥(-) 17:38:28
    每秒有100单的并发量
    北京-喜<-> 17:38:25
    你提交给三方支付之前, 你对外承诺的业务语义,是你的事情做成功了, 结果支付回调回来之后,发现你没做成
    北京-Jerry(-) 17:38:36
    你这个是不是有专门的一个订单服务的,和交易系统是拆分出来的
    杭州-水表哥(-) 17:38:47
    这个问题 搞活动的时候会比较明显
    成都-奋斗(-) 17:39:07
    强制服主库
    北京-喜<-> 17:39:39
    事务没做完,就把订单号+订单状态返回出去了?
    杭州-水表哥(-) 17:39:54
    事务只是提交到数据库, 关键我这边也这边也不知道数据库这边把事务执行完了啊
    北京-喜<-> 17:40:40
    这个事务不是你们自己的代码编写的么?
    杭州-水表哥(-) 17:41:00
    是的
    北京-喜<-> 17:41:06
    那怎么会不知道呢, JDBC处理完 你知道的啊
    杭州-水表哥(-) 17:42:37
    网上我是查了下 有 事务处理成功以后的回调,我今天问下 dba ,他的意思是说 事务只是提交到数据库了,但是不是提交到数据库就意味着执行完成了
    北京-喜<-> 17:43:17
    什么数据库
    杭州-水表哥(-) 17:43:24
    mysql
    北京-liunx(-) 17:44:07
    commit之后成功或者失败都应该会有一个结果吧?
    杭州-东子(-) 17:44:28
    @杭州-水表哥 这查错了吧
    杭州-水表哥(-) 17:46:05
    怎么说
    上海-给你们(-) 17:46:45
    从库策略本来就是做报表之类的查询用的, 如果实时性要求高就别才用主从这种策略
    杭州-水表哥(-) 17:47:03
    网上我是看到有 spring 事务提交后的回调处理,也就是说 事务真正提交后再处理后续的。 喜神,求解惑 我也不太想通过 数据线落地再去处理。
    北京-喜<-> 17:47:15
    不是一件事, 你们DBA说的是 begin 和 commit , begin不等于一定能够commit, 你的问题是commit后,没拿到 提交的信息, spring 那个是java的callback,更不是一件事, commit成功或失败都是可以知道的啊。commit如果返回的是成功,是一定会包成持久化的. 这个是ACID的语义,mysql不能master扩展 也是因为这个原因。本地强一致性,CAP里 不做P。 先落地。后续互相检查在处理,是可以解决的, 但还是没找到根本原因。
    杭州-水表哥(-) 17:51:05
    嗯,这个是第二种方案,还是没找到根本原因
    北京-鹅鹅鹅(-) 17:51:06
    mysql就是不做p吧
    北京-喜<-> 17:51:15
    是啊, 你可以在讲讲处理流程 , 1 2 3 4这样列下
    上海-给你们(-) 17:52:17
    异步支付回调比订单生成早 在支付回调后没找到订单放到队列里,设置一个重试次数就行了, 从用户付款到支付回调,我觉得正常情况下不会比生成订单早,你们订单生成的真复杂。
    北京-alex(-) 17:54:43
    一般都是生成订单在支付的吧
    上海-给你们(-) 17:54:52
    不一定
    北京-alex(-) 17:54:55
    也见过不支付不生成订单的app, 京东淘宝等都是先有订单在支付的
    杭州-水表哥(-) 17:55:39
    下单大致流程
    1.生成结算号
    2.预减库存
    3.执行下单 (生成订单号,调用支付服务增加结算付款信息)
    4.返回客户端 订单 结算信息 (后续可以发起支付操作)
    北京-喜<-> 17:57:13
    全部是同步的?
    杭州-水表哥(-) 17:57:52
    嗯, 压根没异步的场景
    北京-喜<-> 17:58:07
    那可能是 redo log 到 fsync file system的问题, 你问下DBA, redo log刷盘用的什么策略
    杭州-水表哥(-) 17:59:45
    mysql 默认的, redo log 刷盘用的是默认的 ,具体是啥我也不懂
    北京-喜<-> 18:02:04
    就是redo log buffer,会在事务commit的时候,一定持久化到数据文件里
    杭州-水表哥(-) 18:03:04
    也就是说 只要事务提交了,那就肯定数据都持久化到数据库了
    北京-喜<-> 18:04:02
    是的
    杭州-水表哥(-) 18:04:27
    那我知道啥问题了,目前截图给群里的代码是我改造后的,原来的代码事务是无效的, 原来的事务代码 只在 executeOrder 这个方法上面加了事务注解,没生效, 在addOrder 上加了注解就行了.

    相关文章

      网友评论

        本文标题:20180102-12问题整理

        本文链接:https://www.haomeiwen.com/subject/fxldnxtx.html