美文网首页
支付平台架构评审 摘录

支付平台架构评审 摘录

作者: 巨子联盟 | 来源:发表于2018-04-20 19:43 被阅读0次
  • 乐观锁
    更新前先查一下版本号或时间戳,要更新的时候根据版本号和时间戳更新.

观锁在失败的时候再尝试多次更新,导致并发量始终上不去
数据库操作的并发非常少,多数情况下是没有并发的,更新是按照顺序执行的,少有的一些并发通过版本控制来防止脏数据的产生

  • 悲观锁
    for update

  • 行级锁

boolean result = executeSql("update ... set amount = amount - 1 where id = $id and amount > 1");if (result) {    // process sucessful logic} else {    // process failure logic}

扣减库存的场景下使用行级锁,保证数据库更新的安全性,并且通过 where 语句的条件,保证库存不会被减到0以下(上面这个1和>1应该是相等的,实际情况应该传参)
update ... set status = 'doing' where id = $id and status = 'init'
状态转换的时候使用行级锁

保证幂等性利器-->记日志

boolean result = executeSql("update ... set amount = amount - 1 where id = $id and amount > 1");

if (result) {
    int amount = executeSql("select amount ... where id = $id");

    executeSql("insert into hist (pre_amount, post_amount) values ($amount + 1, $amount)");

    // process successful logic
} else {
    // process failure logic
}
  • 设置线程池

首先,我们看一下理想的情况,也就是所有要处理的任务都是计算任务,这时,线程数应该等于 CPU 核数,让每个 CPU 运行一个线程,不需要线程切换,效率是最高的,当然这是理想情况。

这种情况下,如果我们要达到某个数量的 QPS,我们使用如下的计算公式。

设置的线程数 = 目标 QPS/(1/任务实际处理时间)

举例说明,假设目标 QPS=100,任务实际处理时间 0.2s,100 * 0.2 = 20个线程,这里的20个线程必须对应物理的20个 CPU 核心,否则将不能达到预估的 QPS 指标。

但实际上我们的线上服务除了做内存计算,更多的是访问数据库、缓存和外部服务,大部分的时间都是在等待 IO 任务。

如果 IO 任务较多,我们使用阿姆达尔定律来计算。

设置的线程数 = CPU 核数 * (1 + io/computing)

举例说明,假设4核 CPU,每个任务中的 IO 任务占总任务的80%,4 * (1 + 4) = 20个线程,这里的20个线程对应的是4核心的 CPU。

  • 线程队列大小的设置

    队列大小 = 线程数 * (目标相应时间/任务实际处理时间)

举例说明,假设目标相应时间为0.4s,计算阻塞队列的长度为20 * (0.4 / 0.2) = 40。

  • 另外,在设置线程池数量的时候,我们有如下最佳实践。

    1. 线程池的使用要考虑线程最大数量和最小数最小数量。

    2. 对于单部的服务,线程的最大数量应该等于线程的最小数量,而混布的服务,适当的拉开最大最小数量的差距,能够整体调整 CPU 内核的利用率。

    3. 线程队列大小一定要设置有界队列,否则压力过大就会拖垮整个服务。

    4. 必要时才使用线程池,须进行设计性能评估和压测。

    5. 须考虑线程池的失败策略,失败后的补偿。

    6. 后台批处理服务须与线上面向用户的服务进行分离。

  • 缓存的最佳实践

  • 计算缓存数据大小

  • 缓存的业务分离

  • 业务共享一个缓存实例时需要有特殊的key前缀

  • 注意 RDB 备份 copy-on-write 机制,需要 fork 出一个子进程

  • 设置缓存的超时时间

  • 任何缓存的 key 都必须设定缓存失效时间,且失效时间不能集中在某一点,否则会导致缓存占满内存或者缓存穿透。

  • 所有的缓存实例都需要添加监控

  • 低频访问的数据不要放在缓存中

  • 单个缓存 key 的数据过大时,会阻塞其他请求的处理。

  • 尽量不要使用 HGETALL 等集合操作

  • 不能同一个服务各自维护一个本地缓存

  • 在通常情况下,读的顺序是先缓存,后数据库;写的顺序是先数据库,后缓存

  • 在使用缓存时,一定要有降级处理,尤其是对关键的业务环节,缓存有问题或者失效时也要能回源到数据库进行处理。


  • 数据库

  • 在事务处理过程中,禁止执行可能产生线程阻塞的调用,例如:锁等待、远程调用等。

阅读原文

相关文章

网友评论

      本文标题:支付平台架构评审 摘录

      本文链接:https://www.haomeiwen.com/subject/eyfzkftx.html