核心模块-订单模块开发
<h2>整体流程</h2>
<ul>
<li>购物车-></li>
<li>订单确认页面-></li>
<li>提交订单->
<ul>
<li>分布式发号器(订单号)</li>
<li>从购物车中获取数据</li>
<li>组装数据</li>
<li>订单信息入库</li>
<li>删除购物车</li>
<li>减库存操作</li>
</ul></li>
<li>订单生成-></li>
<li>发起支付-></li>
<li>支付系统
<ul>
<li>独立服务做到服务化,也可以说是微服务</li>
</ul></li>
</ul>
<h2>订单主表</h2>
<ul>
<li>订单id在分库分表时,就不能订单id处理了,请使用生成的订单号</li>
<li>取消订单时间,也要记录一下</li>
</ul>
<h2>从分布式场景考虑</h2>
<ul>
<li>所有涉及id的表,都应该使用编号</li>
</ul>
<h2>订单号生成方法,保证唯一</h2>
<ul>
<li>订单表主键id
<ul>
<li>业务量不大场景,不去分库分表。</li>
<li>表数据达到千万级别,就要分表。</li>
</ul></li>
<li>年月日 + 毫秒 + 固定位置随机数
<ul>
<li>在高并发的场景下,会生成相同的订单号</li>
</ul></li>
<li>年月日 + 毫秒 + 固定位置随机数 + 用户id后三位
<ul>
<li>在高并发的场景下,仍然会生成相同的订单号。</li>
<li>不建议使用全部位数的用户id,这样会把用户id暴露给用户,不安全。建议在用户表中生成一个区别于用户id的数字的字段,只用于生成订单号使用</li>
</ul></li>
<li>-redis incr
<ul>
<li>订单id不建议使用redis,会增加网络请求,稳定性也会减小</li>
<li>是incr字符串类型中使用,将 key 中储存的数字值增一</li>
</ul></li>
<li>雪花算法 php-snowflake
<ul>
<li><a href="https://github.com/52fhy/IDWork">https://github.com/52fhy/IDWork</a></li>
<li>推荐使用此算法,在分布式中使用最广。</li>
<li>在分布式中,部署多台服务器,在高并发场景下,支持生成唯一订单id。</li>
<li>基本每秒可以产生400万的唯一性id</li>
<li>php-snowflake就是一个类库文件,也可以通过提供C的源码版本,进行编译.so文件,成为php的扩展文件来使用</li>
<li>在并发量特别大时,订单编号重复机率非常小,可以忽略不计</li>
</ul></li>
</ul>
<h2>可变参数</h2>
<ul>
<li>可以使用数组作为可变参数</li>
</ul>
<h2>取消订单</h2>
<ul>
<li>使用redis有序集合
<ul>
<li>将订单编号,过期时间戳存入到redis有序集合中</li>
<li>使用thinkphp命令行->自定义指令,使用命令行形式对redis有序集合存放的数据进行消费</li>
<li>注意:thinkphp命令行操作是有一定的bug,要注意</li>
</ul></li>
<li>不挂断地运行命令
<ul>
<li>nohup php think 自定义命令 > 日志文件路径 &</li>
<li>当这个进程挂了,要有一个监控机制</li>
</ul></li>
</ul>
<h2>队列开多个服务跑脚本运行处理时</h2>
<ul>
<li>如果同一时间获取到同一个消息,该怎么去避免这种情况或者进行处理</li>
<li>从redis中取出订单id之后,在mysql中查一下这行数据是否需要处理,并加一个乐观锁或悲观锁,如果是需要处理的那就处理,记得加mysql事务,</li>
<li>另一个进程刚好也读到这个id,读数据库,因为上个进程有事务和锁,也不怕这个进程再次改动</li>
<li>并且在此基础上还可以使用redis来实现锁,假如我第一个进程取出一个值,先判断下有没有这个id的锁存在,不存在就用redis的setex加一个锁,然后再处理逻辑,如果存在就跳过本次操作</li>
</ul>