第三次博客

目录

1.患者端住院功能的实现(可以自助选择床位)

并发超卖 - 两个患者同时抢同一张床位

第二个是:死锁不释放————患者锁定床位后跑了

最后是恶意刷号 ————一个人创建无数个申请

住院流程

2.使用支付宝支付方面的测试

数据库设计

Controller方面

Service层

试错策略

最后策略

高并发场景:

总结


本周的产出:

1.患者端住院功能的实现(可以自助选择床位)

首先是住院端功能的实现:

这些方面考虑了很多因素首先明确由于我们的项目没有护士端(工作量太大了)而且也没有想要加护士这一角色所以我的住院部分基本上是由患者本人操作(可以护士辅助)给了患者端很大的权限。随之而来的问题出现了:我们要防止发生很多的东西首先

  1. 并发超卖 - 两个患者同时抢同一张床位

举个例子:

时间线:

T1时刻:床位A的version=0,床位状态=空闲

T2时刻:患者张三看到床位A空闲,点击"选择床位"

T3时刻:患者李四也看到床位A空闲,点击"选择床位"

T4时刻:张三的请求先到后端,执行 UPDATE ... SET status='1' WHERE bed_id=A

T5时刻:李四的请求也到后端,执行 UPDATE ... SET status='1' WHERE bed_id=A

结果:张三和李四都以为自己抢到了床位A,但实际上数据库只能有一个人成功

      这种情况称为"超卖",是典型的并发问题

我的解决方法是添加乐观锁在数据库中加入版本号
粘一下dao:

在加入乐观锁后遇到例子里的问题就可以
T1时刻:床位A的version=0,状态=空闲

T2时刻:张三读取床位A,获取version=0

T3时刻:李四读取床位A,获取version=0

T4时刻:张三执行更新数据库操作,由于数据库当前version 0版本匹配,数据库version变为1

T5时刻:李四执行更新数据库操作,由于数据库当前version=1,不匹配更新失败

结果:李四的请求被拒绝,系统提示"床位已被占用,请重新选

这个在项目里不太好演示不过对数据库的操作其实就是增加了一个版本号建表语句如图:

想到了很容易解决(其实好像在挂号方面也要这样处理上周在赶工忽略了T.T)

第二个是:死锁不释放————患者锁定床位后跑了

这个很讨厌啊如果都来占床位可不行我的解决方案分了两步:

  1. 设定十五分钟时间限制:初始计划是15分钟如果没有确定会提醒医生端几号床还未确认入住,这样可以让护士去看看怎么回事,然后再给15分钟来之后自动取消。不过这个感觉前前后后30分钟太长了最后决定直接给硬性的15分钟所以最后结果就是如果你在选定床位15分钟内不再次点击确定入住我将为你设定为超时。
  2. 每过5分钟扫描一次定时清除超时的床位(这个好像可以用redis的队列啥的希望大佬们给提提意见是不是有更好的办法)

设定时间限制

这个15分钟时间限制的代码放到了乐观锁里

每5分钟扫描代码如下:

兜底机制

最后是恶意刷号 ————一个人创建无数个申请

这个很简单限制每个患者只能申请一次具体不再赘述

住院流程

确定了这些之后接下来就是住院流程:

我的构想是:

首页入口 → 住院申请页面→ 选择科室(显示有空闲床位的科室)→ 选择床位(类似12306选座,实时显示剩余时间)→ 确认锁定(弹窗提示15分钟内需确认入住)→ 倒计时确认页面(15分钟倒计时)→ 点击"确认入住" → 押金缴纳提示 → 完成入院

计费规则:我将计费拆分为小时计费这样就很明显的避免了计费反复申请(申请了又取消)这种情况发生

具体流程如下:

  1. 如果没有被医生安排住院会显示不行:

接下来是住院预约:

选床:

选后有倒计时提醒

缴纳押金:

目前还是没用支付宝沙箱

之后可以点击取消或者是确定入住:

按分钟计费

办理出院:

具体的VO,DO,DAO这些的实现和上篇博客差不多

2.使用支付宝支付方面的测试

流程具体就是这些接下来讲一讲我的支付:

支付这一块以为很简单结果好麻烦T.T

这里用的是支付宝的沙箱模拟(注册账号啥的就不给看了)

首先我来讲一讲这里面的具体流程

数据库设计

首先是数据库设计:加入了两张表:支付记录以及支付回调日志表

主要讲解这一行:

payment_status = Column(Integer, nullable=False, server_default='0', comment='支付状态(0待支付/1已支付/2已退款)')

我的前端会定期轮询检查status的内容,来确保是否已经支付成功(感觉有些问题)

VO,DAO不再赘述dao多是些增删改查

Controller方面

生成押金支付订单并且生成二维码:

自动生成订单号等内容核心功能代码展示:

Service层

试错策略

开始的策略是通过内网穿透依赖支付宝的异步回调,

这个方法用于处理支付宝异步回调的表单解析。

同时在service方法里处理支付宝的异步通知:(这里不粘贴代码了简单写一下思路)首先解析支付宝发送的数据表单,同时由于是异步处理要检查一下订单石是否已经有被支付过(通过数据库里的payment_status)如果已经支付过直接返回(成功支付)给支付宝即可由于是同一个订单订单的基本内容不会再次进行更新。接着就是更新支付记录如果成功支付将payment_status更新为1表示已经支付成功(目前有些问题,虽然已经在用cpolar但是还是会收不到支付宝的)
 

最后策略

经过检查后发现一个神奇的问题:

之前用AI写了一个测试脚本

我发现不需要经过内网穿透的测试脚本却可以正确的输出订单信息

经过查找发现测试脚本里是对支付宝的主动询问这个过程是不需要内网穿透的加上初始的前端的主动轮询的方法只是机械的调用后端去查询数据库:

这个时候相当于后端在一直机械的等待支付宝的异步请求这就会导致支付状态其实一直没有更新(sandbox状态不稳定,网络波动等因素)

现在改为和测试脚本一样主动询问支付宝。

改后代码如图

也是支付成功了:

这里还有一个小失误(怀疑其实本来就是这里的问题)在支付过程中总是会对我的数据库里不存在的列进行修改(可恶的AI)导致事务一直rollback或许改过后用内网穿透依然可以成功(检查出这个是因为在改用主动询问后还是数据库没有更新,果然大多数情况下还是我自己的问题)不过主动询问依然是可行的。

高并发场景:

解释一下高并发场景的情况:

我们的项目在一开始是面向的中小型医院主动轮询的优点是
简单易实现且这属于兜底机制可以以后加上等待回调也易于实现,并且中小型医院并不像高并发电商那样对这个的要求这么高且主动轮询实际上只是把系统开销转给了支付宝服务器而我们的小项目影响其实没有那么大,我的浅薄理解是:主动询问的策略是完全可行的还不用暴露公网。

总结

这是上周和这周前段时间的工作内容。主要是在支付这里花费了一些时间,一开始没开内网穿透就昏天黑地的写支付模块,写完发现不行后找了好久的原因,还是不能太相信AI的能力虽然有些时候确实很好用,但是主观能动性是比AI更有用的东西。

明天我把最近的工作内容再写一篇博客(主要是前端页面的美化和一些其他细节的实施还有住院退款啥的)目前来看基本业务算是已经基本完善了,接下来的工作就是对接入的AI进行的处理了

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐