Internet Consistency Architecture Design -- Inventory Deduction Consistency

Internet Consistency Architecture Design -- Inventory Deduction Consistency

 

 

In a business scenario with complex business, large amount of data, and large amount of concurrency, a typical Internet architecture is generally divided into the following layers:


  • The call layer, usually the browser or APP on the end
  • The site layer is generally the web-server layer returned by assembling html or json
  • The service layer is generally the service layer that provides the RPC call interface
  • Data layer, providing db for solidified data storage

 

 

 

 

The process of deducting inventory

 

For inventory business, there is generally an inventory service that provides RPC interfaces such as inventory query, deduction, and setting:

 

    1. Inventory query, stock-service essentially executes

        select num from stock where sid=$sid

 

    2. Inventory deduction, stock-service essentially performs

        update stock set num=num-$reduce where sid=$sid

 

    3. Inventory settings, stock-service essentially performs

        update stock set num=$num_new where sid=$sid

 

 

 

Before the user places an order, the inventory is generally inquired, and the deduction is allowed only when there is enough inventory:

 

    Example: Total Inventory = 5

 

 

When the user places an order, the inventory is then deducted:

 

    For example: after deducting 3 items, the remaining 2

 

 

 

 

 

fault tolerance

 

       In terms of fault tolerance, the architecture often needs a redo, in case the first deduction fails, redo will be called to make up for it.

 

       When retrying, there may be repeated deductions. If there is a retry fault tolerance mechanism at the database level, it may cause a deduction to be executed twice, and eventually a negative error inventory will be obtained.



 

    Reason : Because the "deduction" operation is a non-idempotent operation, it cannot be performed repeatedly.

 

    Solution : Change the deduction to a setting.

 


 

     The same is to buy 3 units of goods. By setting the inventory operation, even if there is a retry fault tolerance mechanism, you will not get the wrong inventory. Setting the inventory is an idempotent operation.

 

 

 

 

 

Commodities deducted under high concurrency

 

    Inquire


 

 

    concurrent purchase

 

  • User 1 purchased 3 inventory, so the inventory should be set to 2
  • User 2 purchased 2 inventory, so the inventory should be set to 3
  • 这两个设置库存的接口并发执行,库存会先变成2,再变成3,导致数据不一致(实际卖出了5件商品,但库存只扣减了2,最后一次设置库存会覆盖和掩盖前一次并发操作)

 

   

    原因:设置操作发生的时候,没有检查库存与查询出来的库存有没有变化。

 

    解决方法:修改设置的sql

 

    修改前:

    update stock set num=$y where sid=$sid

    修改后:

    update stock set num=$num_new where sid=$sid and num=$num_old

 

    这正是大家常说的“Compare And Set”(CAS),是一种常见的降低读写锁冲突,保证数据一致性的方法。

 

 

 

 

其他解决方法

 

    1. 数据一致性:通常方法是使用乐观锁解决(时间戳、版本号)

 

    2. 可以用redis的事务性解决扣除库存问题,但是小心数据丢失,实际使用还要看业务

 

    3. 能否用事务解决?容易死锁,而且吞吐量低,不建议。

 

    4. 能否用分布式锁,如:setnx、mc、zookeeper?可以,但是吞吐量高不高?

 

    5. 使用队列,在数据库侧串行化执行,降低锁冲突。

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326306737&siteId=291194637