Redis - 在电商购物车场景下的实战分析

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis - 在电商购物车场景下的实战分析

1. 购物车需求背景与业务整体设计

1.1 写在前面

1.1.1 需求背景

商城购物车模拟了传统的现实世界中真实存在的购物车的功能,便于用户挑选心仪商品统一结算等。同时还能在这个点上加以创新,加一些其他的功能。比如:比价,推荐(可作为商家的竞价广告位)等,甚至还可以统计数据告诉卖家,有多少人添加了购物车(代表有购物意向),结果没有付款(尝试分析原因)。

1.1.2 购物车的妙用

购物车在实际使用中对用户来说,兼具凑单、促销、收藏的功能。


  1. 凑单

在用户浏览商品详情页的时候,有两种选项:一种是“立即购买”, 另一种是“加入购物车”。当用户本身需求较多,想一次购买多种商品, 或者参与到优惠活动中(如满减、满赠等),这时候会将商品加入购物车进行凑单。

  1. 促销

购物车还有促销方面的功能,用于提高客单价。当有促销活动(满减、满赠)时,用户将商品加入购物车之后,可以查看是否满足优惠条件和优惠之后的金额(不包含优惠券)。

  1. 收藏

对于大部分用户来说,购物车发挥更多的是收藏的作用:“这东西看着不错,等以后再下单。”另外还有筛选的作用。比如笔者网购时, 会先加入购物车收藏,后面有时间再在购物车中筛选之后购买。

1.2 业务设计

1.2.1 通用显示

  1. 商品信息
  2. 促销信息
  3. 选中状态

默认全选、默认全不选、继承上次选中

  1. 结算

1.2.2 离线购物车

离线购物车指的是用户在未登录状态下把商品加入购物车,一般通过创建虚拟用户实现。为了更好的用户体验,需要让用户在下单之前,允许未登录先将商品加入购物车。

用户登录之后,涉及离线购物车和在线购物车合并。首先判断当前是否有离线购物车,然后将离线购物车的数据和在线购物车的数据进行合并。

1.2.3 商品监控

  1. 库存监控

设置库存提醒值,判断当前商品的数量,当库存数大于0并 小于提醒值时,提醒用户库存不足,请尽快下单;当库存数等于0时, 提醒无货。

  1. 状态监控

当商品下架后,提示商品无效;

无效商品进入无效商品列表中,可批量清除。

  1. 价格监控

购物车的商品价格变动时给用户提示,比如降价20元,会对用户的消费决策产生影响。

1.2.4 分类排序

  1. 商家店铺,将不同店铺的商品分开;
  2. 优惠不同,在购物车中将优惠活动相同的商品聚合在一起;
  3. 加入时间,按照加入购物车的时间倒序排列,最近添加的商品排列在 前。

1.2.5 促销信息

购物车中显示促销相关信息,类似满减、满赠、赠品等信息。例如在购物车中显示“满500减100”、“全场满减”、“商品的赠品有哪些”。还可以引导客户去店铺领取优惠券。在购物车中展示促销信息对提高客单价有良好效果,笔者认为目前最好用的购物车非京东莫属。

1.2.6 商品推荐

在购物车底部,是最好的商品宣传位,可以添加为商品推荐区域。 至于商品推荐的内容,会根据用户数据做定向推荐,这里不做扩展。

1.2.7 编辑

编辑购物车时主要可以进行的操作:删除商品、加减商品数量、更改选中状态、更改商品规格等。

1.2.8 结算

在购物车选中商品时,会实时算出订单金额。在购物车中计算时,需要将优惠金额算进去。

计算优惠金额还需要考虑满减促销、多种优惠券同时满足订单时用户自主选择还是推荐最优券等等。

2. 购物车核心链路和技术方案设计

2.1 核心链路

2.2 技术方案设计

部分电商公司对于购物车数据会选择不落库处理,只做Redis缓存;本次案例以Redis为主,同时通过RocketMQ将购物车数据异步更新到MySQL,不需要去保证Redis缓存和MySQL持久化的数据一致性,数据库只是作为数据备份。

业务上来说,购物车其实是临时性的数据。仅仅是把一些商品再购物车里进行暂存,迟早会购买(从购物车里删除),或者长时间没有购买,已经遗忘了加购过什么商品。就算在极端情况下丢失数据,也影响不大,这时用户重新加入就好了。

2.2.1 Redis

  • 缓存穿透
    当请求穿透缓存时,通过写入空缓存、分布式锁限制MySQL的负载。

2.2.2 表结构

-- auto-generated definition
create table cart
(
    id              bigint auto_increment comment '主键ID'
        primary key,
    user_id         bigint         default 0                 not null comment '用户ID',
    product_sku_id  bigint         default 0                 not null comment '商品SKU ID',
    product_sku_num int            default 0                 not null comment '商品SKU数量',
    add_amount      decimal(10, 2) default 0.00              not null comment '加购价格',
    selected_status tinyint        default 1                 not null comment '选中状态 0:未选中 1:已选中',
    is_deleted      tinyint        default 0                 not null comment '是否删除 0:未删除 1:已删除',
    create_time     datetime       default CURRENT_TIMESTAMP not null comment '创建时间',
    update_time     datetime       default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间'
)
    comment '购物车表';
create index idx_product_sku_id
    on cart (product_sku_id);
create index idx_user_id
    on cart (user_id);

2.2.3 MQ

加入购物车/更新购物车通过RocketMQ异步入库

3. 购物车的阈值检查与重复加入逻辑

3.1 为什么淘宝购物车要设置上限?

3.1.1 回归原始 - 拟物

实体购物车因为有物理的空间限制,理论上可以购买的商品件数和空间是有限的,因此电商的购物车其实在拟物化上也沿袭了这一设计。

站在平台和商家的立场考虑,购物车上限的提示是在一定程度上引导用户去结算或者清理的,提升购物车商品的曝光量,同时也是希望用户把购物车和收藏夹的场景区分开来的,保留购物车的核心功能。

3.1.2 需求大小与价值衡量

  1. 需求大小

从我自身的使用上,我目前还未遇到过购物车超过上限的情况,但是基于淘宝天猫这么大超过8亿的用户群体,碰到购物车超过上限的比例如果只有1%,那绝对值也有庞大的800万用户。

  1. 价值衡量

电商购物最终一定是以交易成交为目的的,也就是解决这个问题能否提升用户下单率和成交件数。这个其实是不一定的,当购物车上限过多时,有可能用户的购买决策会更难,周期可能会更长,同时购物车过多商品用户也会表示很难找到自己想结算的商品,所以在需求的价值上来说是需要慎重衡量的。

  1. 解决方案

(1)引导用户结算或者清理;

(2)引导用户先添加收藏夹再添加购物车;

(3)类似花呗限时提额的操作;

(4)类似美团外卖多个购物车的场景;

(5)在大促是限时提高购物车的上限。

3.1.3 技术和性能

在大促时,系统本来已经面临千万级上亿级别的并发量,为了避免购物车商品图片、价格等信息加载不出来,出现卡顿等情况,设置上限是保证用户体验的一个手段,当用户不能添加购物车需要清理购物车,和进入购物车出现卡顿或加载不出来相比,影响相对较小。

购物车结算涉及到跨店铺满减、商品库存、优惠券、订单金额计算等多达几十个服务的调用

因此技术上为了避免宕机或者影响用户无法结算等糟糕的体验,设置购物车上限是一种产品上的妥协。

3.2 购物车需要设置哪些上限

  1. 购物车单个SKU上限
  2. 购物车加购SKU上限

3.3 重复加入

  1. 不校验重入逻辑
  2. 校验重入逻辑
@Slf4j
@Component
public class RedissonUtils {
    @Resource
    private RedissonClient redissonClient;
    public boolean lock(String key, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(key);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("[RedissonUtils][lock] - tryLock异常", e);
        }
        return false;
    }
    public void unLock(String key) {
        RLock lock = redissonClient.getLock(key);
        if (ObjectUtils.isNotEmpty(lock)) {
            lock.unlock();
        }
    }
}

4. 购物车加入商品多线程并发问题解决

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
19天前
|
缓存 监控 NoSQL
【Redis性能瓶颈揭秘】「调优系列」深入分析热Key的排查策略和解决方案
【Redis性能瓶颈揭秘】「调优系列」深入分析热Key的排查策略和解决方案
64 0
|
2月前
|
缓存 NoSQL 关系型数据库
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
你们有多少人是被面试官问到过Redis和MySQL的数据一致性如何保证的? 你们是否考虑过在高并发场景下,Redis与MySQL的同步会有哪些问题?该如何解决? 本篇文章会带大家详细了解,让你知其然,知其所以然,吊打面试官。
356 0
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
|
19天前
|
缓存 运维 NoSQL
【Redis故障排查】「连接失败问题排查和解决」带你总体分析和整理Redis的问题故障实战开发指南及方案
【Redis故障排查】「连接失败问题排查和解决」带你总体分析和整理Redis的问题故障实战开发指南及方案
43 0
|
19天前
|
缓存 NoSQL Shell
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
24 0
|
19天前
|
存储 缓存 NoSQL
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)(一)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)
41 0
|
21天前
|
NoSQL Redis
Netty实战:模拟Redis的客户端
Netty实战:模拟Redis的客户端
11 0
|
28天前
|
存储 NoSQL Redis
KubeSphere 核心实战之二【在kubesphere平台上部署redis】(实操篇 2/4)
KubeSphere 核心实战之二【在kubesphere平台上部署redis】(实操篇 2/4)
22 0
|
1月前
|
消息中间件 存储 缓存
【Redis实战】有MQ为啥不用?用Redis作消息队列!?Redis作消息队列使用方法及底层原理高级进阶
【Redis实战】有MQ为啥不用?用Redis作消息队列!?Redis作消息队列使用方法及底层原理高级进阶
|
2月前
|
存储 NoSQL 关系型数据库
轻松打卡:使用Spring Boot和Redis Bitmap构建高效签到系统【redis实战 四】
轻松打卡:使用Spring Boot和Redis Bitmap构建高效签到系统【redis实战 四】
61 0
|
2月前
|
NoSQL Java Redis
Spring Boot和Redis Geo实现附近的人【redis实战 三】
Spring Boot和Redis Geo实现附近的人【redis实战 三】
64 0