商城系统ID(如用户、商品、订单等)生成规则

发布时间 2023-07-03 16:56:16作者: 夏末-LateSummer

生成订单ID要满足哪些条件?

全局唯一:如果订单ID重复了,肯定要完蛋。
高性能:要做到高并发、低延迟。生成订单ID都成为瓶颈了,那还得了。
高可用:至少要做到4个9,别动不动就宕机了。
易用性:如果为了满足上述要求,搞了几百台服务器,复杂且难以维护,也不行。
数值且有序递增:数值占用的空间更小,有序递增能保证插入MySQL的时候更高性能。
嵌入业务含义:如果订单ID里面能嵌入业务含义,就能通过订单ID知道是哪个业务线生成的,便于排查问题。

分布式、高性能、高可用的订单ID生成算法——雪花算法,完全能满足上述要求。雪花算法生成ID是Long类型,长度64位。:

第 1 位: 符号位,暂时不用。 第 2~42 位:共41位,时间戳,单位是毫秒,可以支撑大约69年 第 43~52 位:共10位,机器ID,最多可容纳1024台机器 第 53~64 位:共12位,序列号,是自增值,表示同一毫秒内产生的ID,单台机器每毫秒最多可生成4096个订单ID。

同一毫秒内,订单ID的序列号自增。同步锁只作用于本机,机器之间互不影响,每毫秒可以生成4百万个订单ID,非常强悍。生成规则不是固定的,可以根据自身的业务需求调整。如果你不需要那么大的并发量,可以把机器标识位拆出一部分,当作业务标识位,标识是哪个业务线生成的订单ID。

 

雪花算法缺点?

雪花算法严重依赖系统时钟。如果时钟回拨,就会生成重复ID。解决方案比如美团的Leaf(美团自研一种分布式ID生成系统),为了解决时钟回拨,引入了Zookeeper,原理也很简单,就是比较当前系统时间跟生成节点的时间。

 

为什么不能使用UUID?

32位字符串会占用更大的空间,无序的字符串作数据库主键,每次插入数据库的时候,MySQL为了维护B+树结构,需要频繁调整节点顺序,影响性能。况且字符串太长,也没有任何业务含义。

 

常见场景

问:我现在需要对一个商场项目设计一个购买功能,请问如何避免超卖问题,并设计商品数据库表,描述用户从前端传来的数据到后端的逻辑过程。

要避免超卖问题,你可以采取以下几个步骤:

1. 数据库事务管理:使用数据库事务来确保购买过程的原子性。这意味着要么整个购买过程成功,要么回滚到购买前的状态,以防止多个用户同时购买同一商品。

2. 库存管理:在商品数据库表中,包含一个字段用于记录商品的库存数量。在用户购买商品时,首先要检查商品的库存是否充足。如果库存不足,需要给用户提示商品已售罄或者暂时不可购买。

3. 并发控制:在多线程或多用户同时购买商品的情况下,需要进行并发控制,避免超卖问题。可以使用悲观锁或乐观锁机制,或者利用数据库的事务隔离级别来控制并发访问。

4. 限制购买数量:可以在商品数据库表中添加一个字段,用于限制用户每次购买的最大数量。在用户提交购买请求时,检查用户购买数量是否超过限制。

5. 更新库存:在用户成功购买商品后,需要及时更新商品库存数量。可以使用数据库的原子操作(例如UPDATE语句)来减少库存数量,并确保不会出现并发更新问题。

以下是用户从前端传来的数据到后端的逻辑过程的大致描述:

1. 用户在前端界面选择要购买的商品,并提交购买请求。
2. 前端将购买请求发送到后端服务器。
3. 后端接收到购买请求后,首先验证用户的身份和权限,确保用户具有购买商品的权限。
4. 后端根据商品ID在商品数据库表中查询该商品的库存数量。
5. 后端检查商品库存是否充足,如果库存不足,则返回错误信息给前端,提示商品已售完或者暂时不可购买。
6. 如果库存充足,后端开始处理购买请求。
7. 后端使用事务开始购买过程,首先锁定商品记录以避免并发访问问题。
8. 后端再次验证商品库存是否充足,以防止在处理购买请求期间库存发生变化。
9. 如果库存不足,则回滚事务并返回错误信息给前端,提示商品已售罄或者暂时不可购买。
10. 如果库存充足,后端更新商品库存数量,减少对应商品的库存。
11. 后端生成订单并保存到订单数据库表中。
12. 后端提交事务,释放商品记录的锁定。
13. 后端返回购买成功的信息给前端,并显示订单详情。
14. 后端根据需要进行其他操作,例如生成支付信息、发送邮件通知等。

在设计商品数据库表时,可以考虑以下字段:

1. 商品表(Product):
- 商品ID(Product ID):唯一标识商品的ID。
- 商品名称(Product Name):商品的名称。
- 商品描述(Product Description):商品的详细描述。
- 商品价格(Product Price):商品的价格。
- 商品库存(Product Stock):商品的库存数量。
- 其他字段根据需求添加。

2. 订单表(Order):
- 订单ID(Order ID):唯一标识订单的ID。
- 用户ID(User ID):下单用户的ID。
- 商品ID(Product ID):购买的商品ID。
- 购买数量(Quantity):购买的商品数量。
- 订单金额(Total Amount):订单的总金额。
- 订单状态(Order Status):订单的状态,例如待支付、已支付、已发货等。
- 其他字段根据需求添加。

以上是一个基本的设计,你可以根据实际需求进行调整和扩展。在实际开发中,还需要考虑数据校验、安全性、异常处理等方面的细节,并结合具体的框架和技术进行实现。

 

问:秒杀系统如何设计? 

从系统的两大性能瓶颈入手:网络传输(使用CDN缓存静态页面),访问硬盘(数据库读取数据,使用Redis缓存数据)。使用锁保证一致性。使用限流避免过多的访问量。

 

参考文献:

请问商城系统应如何设计ID(如用户、商品、订单等)生成规则? - 一灯架构的回答 - 知乎 https://www.zhihu.com/question/23656839/answer/2472423635