Skip to content

幂等性

一锁、二判、三更新

一锁:第一步,先加锁(请求一个唯一ID过来)。可以加分布式锁、或者悲观锁都可以。但是一定要是一个互斥锁!

二判:第二步,进行幂等性判断。可以基于状态机、流水表、唯一性索引等等进行重复操作的判断。

三更新:第三步,进行数据的更新,将数据进行持久化。

秒杀

  1. 静态缓存
  2. nginx 负载均衡
    三种方式:DNS轮询、IP负债均衡、CDN
  3. 限流机制 方式:ip限流、接口令牌限流、用户限流、header动态token(前端加密,后端解密)
  4. 分布式锁 方式: 1. setnx + expire (非原子性,redis2.6 之后set保证原子性) 2. 释放锁超时 (开启守护进程自动续时间) 3. 过期锁误删其他线程(requestId验证或者lua脚本保证查 + 删的原子性)
  5. 缓存数据 方式: 1. 缓存击穿:缓存数据预热 + 布隆过滤器/空缓存 2. 缓存雪崩:缓存设置随机过期时间,防止同一时间过期
  6. 库存及订单
    1. 扣库存
      1. redis 自减库存,并发场景下可能导致负数,影响库存回仓:使用lua脚本保证原子性
      2. redis预扣库存之后,然后使用异步消息创建订单并更新库存变动
      3. 数据库更新库存使用乐观锁:where stock_num - sell_num > 0
      4. 添加消息发送记录表及重试机制,防止异步消息丢失
    2. 创建订单
      1. 前端建立websocket连接或者轮询监听订单状态
      2. 消费验证记录状态,防止重复消费
    3. 回仓
      1. 创建订单之后发送延时消息,验证订单支付状态及库存是否需要回仓

秒杀,需要支持 100W 以上 QPS

CDN边缘计算扛前端静态页面流量,设定概率,一部分用户请求直接被前端js脚本拒绝,不发请求直接显示秒杀结束。lvs keepalive nginx集群负载均衡流量到网关集群,网关鉴权,令牌桶限流,流量一致性哈希进入redis多副本分片集群,库存拆分给redis各个节点去抢,decr命令或lua脚本原子性扣减库存,抢了之后发送消息到RocketMQ集群,返回提示订单创建中,消费者集群异步写入订单到PolarDB集群,消费成功后告知用户成功

设计微博首页,需要拉取所有关注用户的最近 20 条微博

抢红包算法设计

php
<?php
/**
 * @param $totalMoney float 总金额:元
 * @param $num int 红包数量
 * @return array 红包列表
 */
function createRedPack(float $totalMoney,int $num)
{
    //剩余的 ,单位 分
    $hasMoney = $totalMoney * 100;
    //一分钱
    $min = 1;
    $res = [];
    for ($i = 1;$i <= $num;$i++)
    {

        if ($i != $num)
        {   //剩余的钱-($num-$i)
            $max = $hasMoney - ($num - $i) * $min;
            // 防止每个金额差距过大
            if (intval($hasMoney/($num - $i)) > 0)
            {
                $max = min($max,intval($hasMoney/($num - $i)));
            }


            $money = random_int($min,$max);
        }else
        {
            $money = $hasMoney;
        }
        $hasMoney -= $money;
        $res[] = $money/100;
    }
    //打乱
    shuffle($res);
    return $res;
}
$arr = createRedPack(200,10);
echo '红包结果:'.json_encode($arr).PHP_EOL;
echo '共:'.count($arr).'个'.PHP_EOL;
echo '共:'.array_sum($arr).'元'.PHP_EOL;
"输出:
红包结果:[1.37,6.63,21.67,9.4,14.49,98.55,5.44,2.93,28.64,10.88]
共:10个
共:200元
";

设计一个短链系统

插入数据库,或的id(或发号器?)然后对id进行加密,就的到 x.com/jiami(1) = x.com/aaaaa

接口设计

鉴权部分设计

防超卖

乐观锁

悲观锁

Redis分布式锁

Saas项目架构设计

每个表都要分配商户id?

单点,单用户

单点:SSO,输入账号密码,登录成功 ,重定向的url加上token和code等参数,新url对code和token判断并哪这两个参数去获取(curl发起请求)用户信息,获取后user保存在session里 单用户:保存一登陆的sid,另一个登录的话就将这个sid对应的session销毁

如何设计一个支持十几条业务线的短信发送服务,想到方面越多越好,幂等防重发,防超时,安全,权限验证,成功率,异步,等等情况

商城相关

购物车?

1.购物车只需要保存 sku_id ,数量和时间,查询的时候再反查; 2.未登录的用户,购物车数据就存储在客户端,cookie或localStorage,登录了再同步过去; 3.用redis的hash存储;

搜索?

订单号如何不重复?

1.Snowflake等唯一id算法; 2.订单号由多个参数组成,例如时间戳、商户编号、订单类型、商品类型等,通过组合不同的参数,生成不同的订单号。

支付幂等性?

如何通知用户付款成功

第三方支付回调失败,怎么办?

支付接口防刷和加密?

秒杀?

库存不超卖?

如何取消订单?

给一个文件,一行内容:uri、response_time、code 统计 qps 最大的 uri 使用 Linux 命令统计、后来改用PHP统计

awk '{if ($3 == 200) print $1}' your_file.log | sort | uniq -c | sort -nr | head -n 1

使用awk命令提取文件中的uri列和code列。
使用grep命令筛选出状态码为200的行。
使用sort命令按照uri进行排序。
使用uniq -c命令统计每个uri出现的次数。
使用sort -nr命令按照出现次数降序排序。
使用head命令获取出现次数最多的uri。
提取文件中状态码为200的uri列,按照uri进行排序并统计每个uri的出现次数,然后按照出现次数降序排序,并输出出现次数最多的uri及其出现次数。
<?php
$file = 'your_file.log';

$uriCount = [];

$handle = fopen($file, "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        $parts = explode(" ", $line);
        if (count($parts) >= 3 && $parts[2] == 200) {
            $uri = $parts[0];
            if (!isset($uriCount[$uri])) {
                $uriCount[$uri] = 0;
            }
            $uriCount[$uri]++;
        }
    }

    fclose($handle);

    // Sort uriCount array by value in descending order
    arsort($uriCount);

    // Get the first element of the sorted array
    $maxUri = key($uriCount);
    $maxCount = current($uriCount);

    echo "Max QPS URI: $maxUri, QPS: $maxCount\n";
} else {
    echo "Failed to open file $file\n";
}
?>

给你一个亿大小的文件,文件里包含 IP,设计能快速查询是否存在 IP

红包雨

40亿条个数字,限制1G内存,如何去重,如何找出来?

用bitmap,8bit=1byte;
40bit = 4000000000/8/1024/1024 = 479M;
思路都差不多;不够就用磁盘存来查找;

导出很多行EXCEL

excel2003最大行数65536;Excel 2007开始1048576;
前端导出,分页获取数据合并到excel表中;
注意excel的最大值,限制条件导出,或分成几个表 用扩展php-xlswrite;