面试的时候被问到关于购物车的问题,想请教一下各位大lao

老shi讲的这个模块还是比较简陋的,是把购物车的存到redis里。
然后面试就被问 1.购物车持久化、2.购物车中的商品没库存了或降价了怎么同步过来以及数据多端同步的问题。
当时答的有点烂,后来自己参考淘宝想了下:
1.购物车我暂存redis里,用户一段时间不操作就持久化到数据库,但是这么搞会有多端同步的问题,我也不知道怎么解决。
2.购物车数据的同步是发生在打开购物车页面和勾选商品时发生的,我们只要在用户做这些操作的时候去数据库查就行了,但是这么搞redis不就成了摆设而且mysql负载太大了?

有没有懂得老哥指点一下 感谢

主要是要做前端的负载均衡,因为前端一般压力比较大

参考GPT和自己的思路:

当涉及到购物车功能的持久化和数据同步时,通常有以下几种解决方案:

  1. 购物车持久化
    将购物车数据从Redis中定时写入数据库,以确保数据的持久化。同时,为了解决多端同步的问题,可以使用分布式锁实现数据的同步。

  2. 商品库存和价格同步
    为了避免商品库存和价格发生变化时对用户的错误提示或者过时信息,应该在添加到购物车或下单时检查商品的库存和价格。可以定时或者在用户进行相关操作时,从数据源(数据库或者缓存)中查询商品的最新库存和价格信息。

  3. Redis和MySQL的负载均衡
    为了避免使用Redis和MySQL时出现负载过高的情况,可以通过负载均衡来实现,并使用Redis和MySQL集群来提高系统的性能和可扩展性。

以上是解决购物车持久化和数据同步的常见方案,具体实现应该根据业务需求以及技术选型来确定。


#ifndef CP5_EX15_30_QUOTE_H
#define CP5_EX15_30_QUOTE_H

#include <string>
#include <iostream>

inline namespace EX30 {

    using std::string;
    using std::ostream; using std::endl;
    using std::move;

class Quote {
public:
    Quote() = default;
    Quote(string const& b, double p) : bookNo(b), price(p) { }

    Quote(const Quote&) = default;
    Quote(Quote&&) = default;
    Quote& operator=(const Quote&) = default;
    Quote& operator=(Quote&&) = default;

    virtual Quote* clone() const & { return new Quote(*this); }
    virtual Quote* clone() && { return new Quote(move(*this)); }

    string isbn() const { return bookNo; }
    virtual double net_price(size_t n) const { return n * price; }

    virtual ~Quote() = default;
private:
    string bookNo;
protected:
    double price = 0.0;
};

class Bulk_quote : public Quote {
public:
    Bulk_quote() = default;
    Bulk_quote(const string &b, double p, size_t q, double d) : Quote(b, p), min_qty(q), discount(d) {}

    Bulk_quote(const Bulk_quote& lhs) : Quote(lhs), min_qty(lhs.min_qty), discount(lhs.discount) {}
    Bulk_quote(Bulk_quote&& rhs) noexcept : Quote(move(rhs)), min_qty(move(rhs.min_qty)), discount(move(rhs.discount)) {}
    Bulk_quote& operator=(const Bulk_quote& lhs)
    { Quote::operator=(lhs); min_qty = lhs.min_qty; discount = lhs.discount; return *this; }
    Bulk_quote& operator=(Bulk_quote&& rhs) noexcept
    { Quote::operator=(move(rhs)); min_qty = move(rhs.min_qty), discount = move(rhs.discount); return *this; }

    virtual Bulk_quote* clone() const & { return new Bulk_quote(*this); }
    virtual Bulk_quote* clone() && { return new Bulk_quote(std::move(*this)); }

    virtual double net_price(std::size_t cnt) const override {
        if (cnt >= min_qty) return cnt * (1 - discount) * price;
        else return cnt * price;
    }
protected:
    size_t min_qty = 0;
    double discount = 0.0;
};

double print_total(ostream& os, Quote const& item, size_t n) {
    double ret = item.net_price(n);
    os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << endl;
    return ret;
}

}

其实没有那么复杂的,你要记住,没有十全十美,要做到完美的话,那至少需要庞大的集群和资源支撑你的购物车点选的:

  • 用户数据同步到Redis中,默认是长期存储,时间1天或者7天(避免僵尸用户)。

  • 定时同步Redis数据到MySQL中,做持久化。10分钟或者5分钟。

  • Redis定位页面查询,MySQL定位与其它业务逻辑关联查询。

  • 极端情况,允许丢失几分钟内用户数据。

  • 只有用户真实提交才会调用数据,其它的点选和更新,都是与Redis交互。