项目相关

设计中台库存扣减

高并发设计

主要涉及的问题是预扣减库存时,加锁避免多线程同时扣减的情况(分布式事务)。

业务解决方式

  • 库存分段:将多个总库存分区,每个区分配一个锁来进行库存锁定与扣减;
    • 缺点:库存分段实现麻烦,锁控制的范围不好确定。
  • 库存占用:库存表加锁,在一个库存占用表中插入新数据并解锁,根据库存占用进行下单与扣减。

    库存占用(加锁)的具体流程

  • 整表加锁:利用SELECT * FROM <table_name> WHERE <condition> FOR UPDATE语句,但并行操作被串行化,性能不高;

  • Redis分布式锁:使用Redis的setnx命令获取分布式锁(该命令当key存在时返回0,不存在时创建并设置value返回1),拿到锁并处理完业务后释放锁(del命令删除对应的key);

⚠️注意点:

  • 为了避免Redis挂掉或其他异常导致无法释放锁,在key的value上设置一个时间戳进行超时判断;
  • 为了避免其他线程释放掉未超时到锁,在key的value上添加一个表示线程的特征码。

    扣减过程出错造成的数据不一致

    使用分布式系统的副本解决分布式系统数据异常的问题,一个分布式系统的副本具有多个,而这些副本的一致性分为以下几种:
  • 强一致性:最难实现的最高一致性要求,任何时刻任何用户(节点)读到的任意副本都是最新的数据;
  • 单调一致性:最实用的一致性要求,特定用户(节点)在任何时刻读到的任意副本都是最新的数据,只关注本用户的一致性;
  • 会话一致性:只保证单个用户(节点)在单次会话中读到的都是最新的副本,同一用户不同会话和不同用户之间不保证;
  • 最终一致性:一旦更新成功各个不同副本都是一致的,但达到一致的时间不保证,对于一个用户来说,他只要始终读一个确认的副本,这个副本上的数据永远是满足单调一致性的,但如果切换副本则不确定一致性;
  • 弱一致性:强依赖于应用方的后续工作,用户无法在确定时间内读到更新后的副本。

    数据库相关

    分库分表

    Redis原理

    Java相关

    overload和override

    多态与继承

    多态的概念与原理

    static 与继承

    算法

    找出数组中相加为目标和的两个数字组合
    输入:[1, -1, 5, 4, 2, 3, 1, 2, 2], 4
    输出:[1, 3], [-1, 5], [2, 2], [2, 2], [3, 1], [2, 2]
    1. public List<Pair> findAllPairs(int[] array, int target) {
    2. Map<Integer, Integer> map = new HashMap<>();
    3. List<Pair> res = new ArrayList<>();
    4. for (int i : array) {
    5. if (map.containsKey(target - i)) {
    6. map.put(target - i, map.get(i) + 1);
    7. } else {
    8. map.put(target - i, 1);
    9. }
    10. }
    11. for (int i : array) {
    12. if (map.containsKey(i) && map.get(i) > 0) {
    13. Pair p = new Pair(i, target - i);
    14. map.put(target - i, map.get(i) - 1);
    15. res.add(p);
    16. }
    17. }
    18. }