电商项目——从0到1挑战

电商项目需求分析

电商项目概述

电商业务离不开我们的生活。

设计一个最小化的电商系统,理清电商系统的架构,对电商系统的业务逻辑、系统架构、核心业务流程有一个基本的认知,这个直接用技术实现不就OK了?所以嘛,不仅要深耕上述的技术层面,还要学习和掌握什么是电商的业务需求和系统(技术+业务)

电商类型

  • B2C:面向消费者销售产品和服务商业零售模式 (小米、华为)
  • B2B:企业与企业间通过互联网展开的交易活动商业模式 (1688)
  • B2B2C:B2B、B2C模式结合体 (天猫、京东、唯品会、苏宁易购)
  • C2C:个人与个人之间的电子商务 (淘宝网、咸鱼)
  • O2O:线下商家与互联网称为线下交易平台 (美团、饿了吗)
  • B2G:企业与政府机构的电子商务 (中国政府采购网)

运营方向

  • 传统电商: 淘宝天猫、京东、唯品会、聚美优品、当当
  • 社交电商: 拼多多、京东、国美、苏宁
  • 网红电商: 抖音、快手
  • 内容电商: 头条三农领域

电商术语

  • PV: Page view,即网站被浏览的总次数
  • UV: Unique Vister的缩写,独立访客
  • CR: ConversionRate的缩写,是指访问某一网站访客中,转化的访客占全访客的比例(订单转化率=有效订单数/访客数)
  • SPU: Standard Product Unit (标准化产品单元),SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。 例如:华为手机中的处理器、电池等等。
  • SKU是物理上不可分割的最小存货单元SKU即库存进出计量的单位(买家购买、商家进货、供应商备货、工厂生产都是依据SKU进行的),在服装、鞋类商品中使用最多最普遍。
    例如纺织品中一个SKU通常表示:规格、颜色、款式。SKU是物理上不可分割的最小存货单元

一个最小化的电商系统,也依然是非常复杂的,需求永远不明确,永远在变化,唯一不变的只有变化。应该适应变化,并且拥抱变化。在需求还不太明确的情况下,比较可行的方案:首先搭建不太会发生变化的核心系统,然后尽量简单地实现一个最小化的系统,后续再逐步迭代和完善

设计电商系统的核心流程

从需求阶段开始,需求分析的工作还不是由开发者完成的真的是,因为很多项目交付以后,仍需要不断地进行修改和变更,用户不满意,开发者也很痛苦,背后的原因是缺失了需求分析的步骤,所以应该掌握一些用于需求分析的方法。

先明确下面两个点(业务需求)

  • 这个系统(或者功能)是给哪些人用的
    • 首先是买东西的人,即“用户”;其次是卖东西的人,即“运营”;还有一个非常重要的角色就是出钱的人,即“管理者”(请记住,在设计任何一个系统的时候,出钱的人的意见都是重要的,甚至可以说是最重要的)
  • 这些人使用这个系统是为了解决什么问题
    • 用户为了买东西,运营为了卖东西,管理者需要通过系统了解自己所得的收益。
      电商系统用例图如下:
      在这里插入图片描述
      做业务需求的主要目的是理清楚业务场景是怎样的。
      电商系统的业务流程:从用户浏览商品 -> 将心仪的商品加入购物车 -> 提交订单 -> 确认订单(计算订单中商品总价格…)-> 用户支付 -> 支付成功后运营人员为支付状态为成功的订单发货,邮寄给用户 -> 用户收到货后并确认收货在这里插入图片描述

根据核心流程划分模块

对上述电商业务流程做细化成时序图(这里时序图并不是很详细哦,只是根据上述流程细化一点罢了)
在这里插入图片描述

  • 用户浏览商品,这个步骤需要通过一个商品模块来展示商品详情页,用户可以从中获取所浏览商品的详细介绍和价格等信息
  • 用户把选好的商品加入购物车,这个步骤需要使用一个购物车模块来维护用户购物车中的商品
  • 用户下单,这个步骤需要基于一个订单模块来创建新订单。订单创建好了之后,系统需要把订单中的商品从购物车中删减掉
  • 订单创建完成后,系统需要引导用户付款,即发起支付流程,可通过一个支付模块来实现支付功能,用户成功完成支付之后,系统需要把订单的状态变更为“已支付”
  • 成功支付之后,运营人员就可以发货了,发货之后,系统需要扣减对应商品的库存数量,这个步骤需要基于一个库存模块来实现库存数量的变更,同时系统还需要把订单状态变更为“已发货”
  • 用户收到商品,在系统中确认收货,系统需要把订单状态变更为“已收货”。
    所以,电商项目的购物业务的核心功能模块是:商品、购物车、订单、支付和库存
    管理员的查看报表,运营人员的进货出货这些没有覆盖到,这里后续我扩展下
    在这里插入图片描述
  • 商品:维护和展示商品的相关信息
  • 订单:维护订单信息和订单状态,计算订单金额。
  • 购物车:维护用户购物车中商品的信息。
  • 支付:负责与系统内外部的支付渠道对接,实现支付功能。
  • 库存:维护商品的库存信息。
  • 促销:制定促销规则,计算促销优惠信息。
  • 用户:维护系统的用户信息,注意,用户模块是一个业务模块,一般不负责用户的登录和认证,这是两个完全不同的功能。
  • 账户:账户模块负责维护用户的账户信息,例如用户的积分、等级、余额。
  • 搜索推荐:提供商品搜索功能,并负责各种商品列表页和促销页的组织和展示,搜索推荐决定用户优先看到哪些商品。
  • 报表:实现数据统计和分析功能,生成报表,为管理者进行经营分析和决策提供数据信息

在实际的电商网站中,促销模块是电商系统中最复杂的一个模块。各种优惠券、满减、返现等促销规则,每一条都非常复杂,再加上这些规则往往还要叠加计算,有时甚至会复杂到连制定促销规则的人都算不清楚。在实际的运营中,所有电商公司几乎都发送过因为促销规则制定失误,导致商品实际售价远低于成本价,使公司受到一定程度的损失。尽管如此,五花八门的促销活动依然是提升销量最有效的手段,因此需要充分利用。

作为电商系统的设计者,需要把促销规则的变化和复杂性控制在促销模块内部,不能因为一个促销模块而导致整个电商系统都变得非常复杂,否则设计和实现将会很难。所以,可以把促销模块与其他模块的接口设计得相对简单和固定,这样系统的其他模块就不会因为新的促销规则改变而随之进行改变。销模块返回一个可以使用的促销列表,用户选择对应的促销和优惠,订单模块把商品、价格、促销优惠等信息,再次传给促销模块,促销模块再返回促销之后的价格。在最终生成的订单中,系统只需要记录订单使用了哪几种促销规则,以及最终的促销价格就可以了。这样,无论促销模块如何变化,订单和其他模块的业务逻辑都不需要随之改变。

总结电商系统设计核心要点

首先,电商系统面向的角色是:用户、运营人员和管理者。这三个角色对电商系统的需求是:用户通过系统来购物,运营人员负责商品的销售,管理者关注系统中的经营数据。电商系统最核心的流程是用户购物的流程,购物流程从用户浏览选购商品开始,加购、下单、支付、运营人员发货、用户确认收货,至此电商系统的购物流程结束。

细化这个流程之后,我们可以分析出支撑这个流程的核心功能模块:商品、订单、购物车、支付和库存。除此之外,一个完整的电商系统还包括促销、用户、账户、搜索推荐和报表这些必备的功能模块。
作为一名开发者,在做需求分析的时候,需要把握的一个要点是:不要一上来就设计功能,而是要先理清业务需求
如果系统业务是复杂而多变的,那么请尽量识别出这部分复杂业务的边界,将复杂业务控制在一个模块内部,从而避免将这种复杂度扩散到整个系统中去。

项目架构图

在这里插入图片描述

项目环境

代码管理和项目发布

  • GitLab
  • Jenkins
  • Nexus

中间件和基础设施

  • MySQL
  • Redis
  • ELK
  • RocketMQ
  • MongoDB
  • Canal
  • Promethus
  • Grafana
  • SpingCloudAlibaba系列

项目运行所需最小环境

  • MySQL: 8.0
  • Nacos: 2.1.0
  • RocketMQ: 4.9.4
  • ElasticSearch: 7.6.1
  • Redis集群: 5.0

项目中将学习的技术问题(重点技术问题)

  • 分库分表、读写分离
  • 分布式事务
  • 全局唯一性ID
  • 分布式Session
  • 分布式链路跟踪
  • 日志收集与展示
  • 商品搜索
  • 分布式锁
  • 服务降级/限流/熔断/隔离
  • 页面静态化
  • 分布式任务调度
  • 数据迁移方案
  • 数据同步方案
  • 多级缓存、缓存预热
  • 高并发秒杀系统实现(秒杀系统的商详页静态化、秒杀系统的隔离、秒杀的削峰和限流等等)

项目学习必备知识

  • 并发编程
  • SpringBoot + Mybatis + MySQL 下的WEB应用开发
  • 普通基础商城项目单体版
  • 分布式基本概念
  • 微服务的基本概念
  • 事务一致性概念、多副本一致概念和CAP理论
  • SpingCloudAlibaba系列组件(Nacos、Seata等等)的作用和基本使用
  • Redis各种数据结构和操作、Redis主从和Redis Cluster基本概念
  • Lua语言的基础语法
  • MongoDB基本概念和操作、MongoDB集群基本概念
  • 消息中间件的基本概念和RocketMQ的基本操作、RocketMQ集群基本概念
  • ELK的基本概念和基本使用
  • JavaScript基础语法
  • Linux的基本概念和操作
  • Nginx基本概念和操作
  • Git的基本操作和Maven基本配置方法和常用命令

后台管理项目多数据源管理方案

整个电商管理后台本质上是一个访问频率比较低的CRUD管理系统,所以本身不需要考虑微服务拆分的事情。接入微服务体系也只是为了能够调用其他的微服务。为了简化业务流程,在做后端管理系统时,并没有严格按照微服务原则进行数据隔离,而是让管理系统直接访问所有的业务数据,那么需要让管理系统可以同时管理多个数据库的数据哦。

电商后台项目需要访问的数据源说明

整个电商项目的数据库设计情况:
在这里插入图片描述
这些不同库中的很多基础数据,除了购物车模块外,都需要由电商管理后台进行统一管理。所以,对于电商管理系统,会采用多数据源管理的方式,尽量快速的完成基础数据维护。其中,订单库由于进行了分库分表,管理比较复杂,所以电商管理后台不会直接访问订单相关的表,而是通过微服务的方式调用订单模块的相关功能来间接管理订单。

电商后台使用MyBatis-plus快速访问多个数据源

电商后台项目使用的MyBatis-plus框架访问数据库。这里设计的电商项目管理数据的方式是直接粗暴的,直接跨多个数据库管理的后台数据

使用Spring提供的AbstractRoutingDataSource

这种方式的核心是使用Spring提供的AbstractRoutingDataSource抽象类,注入多个数据源。

AbstractRoutingDataSource 是 Spring 提供的一个抽象类,用于实现动态数据源路由的功能。它允许在运行时根据某些条件(比如当前线程的上下文)决定使用哪个具体的数据源。

以下组件的逻辑通常用于实现读写分离(一个写库和多个读库),以提升数据库性能。

@Component  // 这个类标记为 Spring 的组件,Spring 容器会自动扫描并创建其 Bean 实例
@Primary // 将该Bean设置为主要注入Bean,当有多个 DataSource Bean 存在时,Spring 默认会注入被标记为 @Primary 的那个 Bean
public class DynamicDataSource extends AbstractRoutingDataSource {
   
   
	// 用来保存当前线程使用的数据源标识
	public static ThreadLocal<String> name=new ThreadLocal<>();
	
	// 数据源注入,注入两个实际的数据源对象,分别代表写库(dataSource1)和读库(dataSource2)
	// 写库
	@Autowired
	DataSource dataSource1;
	// 读库
	@Autowired
	DataSource dataSource2;
	
	
	// 返回当前数据源标识(返回“W”或“R”)  (AbstractRoutingDataSource 的核心方法,用于决定当前线程应该使用哪个数据源)  
	@Override
	protected Object determineCurrentLookupKey() {
   
   
		return name.get();
	}

	/**
	* 实现afterPropertiesSet()方法,返回当前应使用的数据源标识符
	*/
	@Override
	public void afterPropertiesSet() {
   
   
		// 为targetDataSources初始化所有数据源
		// 创建一个 Map<Object, Object>,键是数据源标识(如 "W"),值是实际的 DataSource 对象
		Map<Object, Object> targetDataSources=new HashMap<>();
		// 将写库和读库放入这个 Map 中
		targetDataSources.put("W",dataSource1);
		targetDataSources.put("R",dataSource2);
		// 调用 setTargetDataSources() 设置这些数据源
		super.setTargetDataSources(targetDataSources);
		// 为defaultTargetDataSource 设置默认的数据源
		super.setDefaultTargetDataSource(dataSource1);
		// 调用父类的 afterPropertiesSet() 完成初始化
		super.afterPropertiesSet();
	}
}

将自己实现的DynamicDataSource注册成为默认的DataSource实例后,只需要在每次使用DataSource时,提前改变一下其中的name标识,就可以快速切换数据源。(注解+AOP)

@Component
@Aspect
public class DynamicDataSourceAspect implements Ordered {
   
   
	// 前置通知,在每个访问数据库的方法执行前执行。  
	@Before("within(com.yxx.dynamic.datasource.service.impl.*) && @annotation(wr)")
	public void before(JoinPoint point, WR wr){
   
   
		String name = wr.value();
		DynamicDataSource.name.set(name);
		System.out.println(name);
	}
	@Override
	public int getOrder() {
   
   
		return 0;
	}
}

自定义两个数据源的配置

spring:
	datasource:
		type: com.alibaba.druid.pool.DruidDataSource
		datasource1:
			url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
			username: root
			password: root
			initial-size: 1
			min-idle: 1 
			max-active
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值