后端存储实战课-学习笔记

本笔记内容来源极客时间-李玥老师的后端存储实战


创建和更新订单时,如何保证数据准确无误

重要摘要

  • 一个合格的订单系统,最基本的要求是什么?数据不能错。--说的是数据一致性的问题
  • 订单系统的核心功能和数据:
    • 核心功能:
          创建订单;
          随着购物流程更新订单状态;
          查询订单,包括用订单数据生成各种报表
    • 核心数据:
      订单主表:也叫订单表,保存订单的基本信息。
      订单商品表:保存订单中的商品信息。
      订单支付表:保存订单的支付和退款信息。
      订单优惠表:保存订单使用的所有优惠信息
    • 这几个表之间的关系是这样的:订单主表和后面的几个子表都是一对多的关系,关联的外键就是订单主表的主键,也就是订单号
  • 如何避免重复下单?前端如果发送了重复下单的请求应该怎么版办?
    • 解决办法是,让你的订单服务具备幂等性。什么是幂等呢?一个幂等操作的特点是,其任意多次执行所产生的影响均与一次执行的影响相同。一个幂等的创建订单服务,无论创建订单的请求发送多少次,正确的结果是,数据库只有一条新创建的订单记录。
    • 利用数据库中,表主键的唯一性约束。,我们给订单系统增加一个“生成订单号”的服务,这个服务没有参数,返回值就是一个新的、全局唯一的订单号。在用户进入创建订单的页面时,前端页面先调用这个生成订单号服务得到一个订单号,在用户提交订单的时候,在创建订单的请求中带着这个订单号。这个订单号也是我们订单表的主键,这样,无论是用户手抖,还是各种情况导致的重试,这些重复请求中带的都是同一个订单号。订单服务在订单表中插入数据的时候,执行的这些重复 INSERT 语句中的主键,也都是同一个订单号。数据库的唯一约束就可以保证,只有一次 INSERT 语句是执行成功的,这样就实现了创建订单服务幂等性。
    • 果是因为重复订单导致插入订单表失败,订单服务不要把这个错误返回给前端页面。否则,就有可能出现这样的情况:用户点击创建订单按钮后,页面提示创建订单失败,而实际上订单却创建成功了。正确的做法是,遇到这种情况,订单服务直接返回订单创建成功就可以了。
    • 如何解决更新操作时的ABA问题?
      • 什么是 ABA 问题呢?我举个例子你就明白了。比如说,订单支付之后,小二要发货,发货完成后要填个快递单号。假设说,小二填了一个单号 666,刚填完,发现填错了,赶紧再修改成 888。对订单服务来说,这就是 2 个更新订单的请求。正常情况下,订单中的快递单号会先更新成 666,再更新成 888,这是没问题的。那不正常情况呢?666 请求到了,单号更新成 666,然后 888 请求到了,单号又更新成 888,但是 666 更新成功的响应丢了,调用方没收到成功响应,自动重试,再次发起 666 请求,单号又被更新成 666 了,这数据显然就错了。这就是非常有名的 ABA 问题。
      • ABA 问题怎么解决?这里给你提供一个比较通用的解决方法。给你的订单主表增加一列,列名可以叫 version,也即是“版本号”的意思。每次查询订单的时候,版本号需要随着订单数据返回给页面。页面在更新数据的请求中,需要把这个版本号作为更新请求的参数,再带回给订单更新服务。订单服务在更新数据的时候,需要比较订单当前数据的版本号,是否和消息中的版本号一致,如果不一致就拒绝更新数据。如果版本号一致,还需要再更新数据的同时,把版本号 +1。“比较版本号、更新数据和版本号 +1”,这个过程必须在同一个事务里面执行。具体的 SQL 可以这样来写:UPDATE orders set tracking_number = 666, version = version + 1WHERE version = 8

MySQL如何应对高并发(一):使用缓存保护MySQL

重要摘要

  • 缓存穿透指的是,在读数据的时候,没有命中缓存,请求“穿透”了缓存,直接访问后端数据库的情况。
  • 少量的缓存穿透是正常的,我们需要预防的是,短时间内大量的请求无法命中缓存,请求穿透到数据库,导致数据库繁忙,请求超时。大量的请求超时还会引发更多的重试请求,更多的重试请求让数据库更加繁忙,这样恶性循环导致系统雪崩。
  • 当系统初始化的时候,比如说系统升级重启或者是缓存刚上线,这个时候缓存是空的,如果大量的请求直接打过来,很容易引发大量缓存穿透导致雪崩。为了避免这种情况,可以采用灰度发布的方式,先接入少量请求,再逐步增加系统的请求数量,直到全部请求都切换完成。
  • 还有一种常见的缓存穿透引起雪崩的情况是,当发生缓存穿透时,如果从数据库中读取数据的时间比较长,也容易引起数据库雪崩。--回源数据库的时间过长,导致大量的请求打到了DB上。比如说,我们缓存的数据是一个复杂的数据库联查结果,如果在数据库执行这个查询需要 10 秒钟,那当缓存中这条数据过期之后,最少 10 秒内,缓存中都不会有数据。如果这 10 秒内有大量的请求都需要读取这个缓存数据,这些请求都会穿透缓存,打到数据库上,这样很容易导致数据库繁忙,当请求量比较大的时候就会引起雪崩。
  • 什么是雪崩:大量请求穿过redis,打到DB的现象
  • 怎样防止缓存雪崩现象?这个问题其实问的是怎么保证不要有大量的请求穿过缓存访问到DB。首先,造成这个问题的原因是,缓存不存回源DB导致的。那缓存不存在有两种情况,一是缓存还没生成,这里面有可分为两种场景,一种是应用刚刚启动,系统中大量缓存还没生成,二是自别的数据之前没有被查询过,导致没有生成缓存。二是,缓存失效,而缓存失效又有两种情况,一种是自动失效了,缓存的时间到。一种是发生了数据变更,缓存被主动失效了。
    • 对于应用刚刚启动,缓存还没有生成的情况。可以使用流量回放预热的方式解决。
    • 对于个别缓存没有生成,且这个别的数据在某个时刻点又是热点数据:解决方案,回源DB生成缓存的过程需要加锁。这样只会有一个请求打到DB上。
    • 对于缓存主动失效的场景:解决方案,使用缓存时判断下缓存的剩余的可用时长,低于某个值时,可以对它进行续期
    • 对于主动失效的场景:这里只要保证,回源DB生成缓存的过程加上锁其实就可以了。

重要评论

  • 对于Cache aside和read/write through而带来的数据不一致问题,工作中是这样解决:

        a写线程,b读线程:

        b线程:读缓存->未命中->上写锁>从db读数据到缓存->释放锁;

        a线程:上写锁->写db->删除缓存/改缓存->释放锁;

        这样来保证a,b线程并发读写缓存带来的脏数据问题;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值