电商项目介绍
Posted HelloWouldH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了电商项目介绍相关的知识,希望对你有一定的参考价值。
目录
1.自我介绍
面试官你好,我叫xx,毕业于xxxxx,我从事java程序开发已经四年了,下面我具体说一下我的项目经验.
从2017年至今,我从事java编程工作已经四年了,前面两年我在长沙微猴科技,2019年来到深圳,在深圳和合联众在微猴做过两个项目,一个汽车站管理系统,一个金力飞人力资源管理系统,在和合联众做了一个课程学习管理平台,和优乐淘购物平台
2.项目介绍
我从去年10月开始,一直参与这个商城系统的开发,我们这个系统是b2c模式的电商系统,我简单介绍一下我们这个系统的架构,项目是一个分布式架构项目,后台部分用的是springboot,springsvc,mybatis,权限验证是c罗,前端用的是vue+element ui,总共是7个人做这个项目.
3.购物车模块介绍
购物车与登录模块/订单模块/用户模块/等模块交互
购物车考虑的点很多,比如
*3.1*
我们规定购物车必须要先登录才能使用
经过一个拦截器,根据token判断用户是否登录,如果登录判断Token是否过期,未登录以及过期的提示登陆
*3.2*
账户退出之后,购物车内容必须保存起来(mongoDB)---(直接使用mongo命令连接数据库---创建时,直接使用use [database]命令即可--查看当前数据库:最简单的命令就是db.stats()--直接通过db.xxx.insert(),db.xxx.save()命令来保存数据)
mongodb简介: MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
*3.3*
购物车页面要能够显示商品的详细信息(商品名称、链接、数量、单价、总价)
商品分spu表和sku表,分别代表公共信息和规格信息,详细信息数据可以从sku里面获取
*3.4*
多条商品能够以列表显示;
用hash数据结构保存,购物车 用每个用户一个大key,小key1保存商品名字+数量,value1保存数值,小key2保存商品名+info,vlue2保存json
然后,抽出各个用户中的小key2,存在一个公共的大key里面,保存的时候用hsetnx指令(不存在就从数据库中拿过去保存,有值就什么都不做)
*3.5*
修改删除功能 : 能够调整商品的数量//移除购物车中的商品;
*3.6*
购物车能够添加50件不同的商品;
*3.7*
如果使用优惠券,结算价格相应调整;
*3.8*
购物车中的商品结算后,从购物车中清除;
*3.9*
限购商品数量不能超过限购数量,购买完成后不能再次添加购物车,不限购的不能超过库存;
4.订单模块介绍
交互的模块:登录模块/商品模块/用户模块(加减积分)/支付模块
订单模块维度: 状态机维度(订单状态/支付状态/商品状态/商品支付状态/)----用户信息-----下单时间---支付时间---支付细节
主订单(OrderHeader)的状态枚举有:
处理中/ 成功/ 失败/ 订单取消/ 订单部分取消/ 订单完成/ 订单关闭
- 待支付下单失败
- 待支付待确认
- 待支付已确认
- 待支付确认失败(拒单)
- 待支付确认失败(超时)
- 待支付已取消
- 已支付待下单
- 已支付待确认
- 已支付已确认
- 待退款下单失败
- 待退款确认失败(拒单)
- 待退款确认失败(超时)
- 部分退款已确认
- 已退款下单失败
- 已退款确认失败(拒单)
- 已退款确认失败(超时)
- 已退款已退订
5.秒杀模块介绍
1.秒杀实现
1.秒杀时间非常短,并发访问很高,如果和原网站部署在一起可能使原网站瞬间瘫痪,所以我们单独部署秒杀程序,给他分配独立域名.
2.秒杀之前用户为了不错过活动会频繁刷新画面,这对后台系统来说会造成很大的负载,所以数据库集群,redis集群,以及负载均衡之外,秒杀页面要实现静态化,避免后台系统渲染动态页面消耗过多的资源
3.秒杀需要瞬间增加网络带宽,一方面可以在云端租用临时的带宽资源,另一方面可以把秒杀页面放到CDN节点上面,这样就可以节省,秒杀服务器的带宽
4.为了避免秒杀之前用户提前获取秒杀下单前的URL路径,所以需要对URL路径实行动态化,例如在秒杀开始之后,服务端生成特殊规则的随机数,然后把这些随机数保存在redis上,那么秒杀的时候url地址必须带上这样的随机数才能进入到下单画面,避免秒杀还没开始,就提前下单
5.秒杀倒计时也需要特殊的设计,秒杀开始之前CDN节点上面的js文件的功能是先获取北京时间,然后在html上生成倒计时时钟,秒杀开始时刷新页面,重新加载js文件.也就是秒杀开始那一刻,后台程序在CDN节点上更新了js文件内容,
秒杀开始的时候,用户浏览器会自动刷新,就能加载到这个最新的js文件,于是js文件生成秒杀按钮,用户点击按钮之后js会向后台发起秒杀请求,秒杀之前任何顾客都没办法发起秒杀请求
6.扣减库存不能采用,付款之后扣减库存,因为这会让用户体验糟糕(秒杀到了,付钱的时候才告诉他没有库存) ,我们会使用,下单就立即扣减库存,这意味着用户下单成功,支付的时候一定有货,不会出现提示没库存的现象....还有就是,如果用户下单之后如果超过10分钟没有支付,自动释放库存
7.除此之外还要防止超售/重复购买,超售用redis分布式锁来解决(下面有)
重复购买可以设定一个分布式计数器.实现如下:
判断key为空设置为1,判断不为空,计数器加一
redisTemplate.boundValueOps(id).increment();定义一个拦截器(实现HandlerInterceptor)
8.(秒杀并发问题怎么解决)秒杀我们除了需要用上了数据库集群/redis集群,还有负载均衡,阿里云CDN加速技术...面对海量的请求还是需要做好限流,以及在后台系统引入消息队列,拦截大量的请求
cdn
在CDN网站管理后台,增添域名,等待审核。
审核通过以后,会给你一个CNAME,在阿里云域名管理后台的解析页面,进行解析
2.超售怎么解决
用redis分布式锁来解决
加锁实际上就是在redis中,给Key键设置一个值,为避免死锁,并给定一个过期时间。
SET lock_key random_value NX PX 5000
值得注意的是:random_value
是客户端生成的唯一的字符串。NX
代表只在键不存在时,才对键进行设置操作。PX 5000
设置键的过期时间为5000毫秒。
这样,如果上面的命令执行成功,则证明客户端获取到了锁。
1、String
字符串是最常用的数据类型,他能够存储任何类型的字符串,当然也包括二进制、JSON化的对象、甚至是base64编码之后 的图片。在Redis中一个字符串最大的容量为512MB,可以说是无所不能了。
2、Hash
常用作存储结构化数据、比如论坛系统中可以用来存储用户的Id、昵称、头像、积分等信息。如果需要修改其中的信息,只需要通过Key取出Value进行反序列化修改某一项的值,再序列化存储到Redis中,Hash结构存储,由于Hash结构会在单个Hash元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在String结构里是不存在的。
3、List
List的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis 内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。另外,可以利用 lrange 命令,做基于 Redis 的分页功能,性能极佳,用户体验好。
4、Set
set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,这个时候就可以选择使用set。
5、Sort Set
SQL优化
字段优化
2、VARCHAR的长度只分配真正需要的空间
3、使用枚举或整数代替字符串类型
4、尽量使用TIMESTAMP而非DATETIME
5、单表不要有太多字段,建议在20以内
6、避免使用NULL字段,很难查询优化且占用额外索引空间
建立索引优化
1 根据业务针对性的创建索引
2 值分布很稀少的字段不适合建索引,例如”性别”这种只有两三个值的字段
3 字符字段只建前缀索引
4 字符字段最好不要做主键
5 不用外键,由程序保证约束
6 尽量不用UNIQUE,由程序保证约束
7 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引
SQL查询优化
1、可通过开启慢查询日志来找出较慢的SQL
2、不做列运算:SELECT id WHERE age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边
3、sql语句尽可能简单点 ,大语句拆小语句,减少锁时间;一条大sql可以堵死整个库
4、不用SELECT *
5、OR改写成IN:OR的效率是n级别,IN的效率是log(n)级别,in的个数建议控制在200以内
6、不用函数和触发器,在应用程序实现
7、避免%xxx式查询
8、少用JOIN
9、使用同类型进行比较,比如用’123’和’123’比,123和123比
10、尽量避免在WHERE子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
11、对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
12、列表数据不要拿全表,要使用LIMIT来分页,每页数量也不要太大
调优参数
调优工具
sysbench:一个模块化,跨平台以及多线程的性能测试工具
iibench-mysql:基于 Java 的 MySQL/Percona/MariaDB 索引进行插入性能测试工具
tpcc-mysql:Percona开发的TPC-C测试工具
1 max user connection(设置最大连接数)
最大连接数,默认为0无上限,最好设一个合理上限thread_concurrency:并发线程数,设为CPU核数的两倍
2 back_log (MySql的连接数据达到maxconnections,多少个请求可以被存在堆栈中)
backlog值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果MySql的连接数据达到maxconnections时,
新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即backlog,如果等待连接的数量超过backlog,将不被授予连接资源。可以从默认的50升至500
3.wait_timeout (数据库连接闲置时间)
数据库连接闲置时间,闲置连接会占用内存资源。可以从默认的8小时减到半小时
skipnameresolve
禁止对外部连接进行DNS解析,消除DNS解析时间,但需要所有远程主机用IP访问
keybuffersize
索引块的缓存大小,增加会提升索引处理速度,对MyISAM表性能影响最大。对于内存4G左右,可设为256M或384M,
通过查询show status like’keyread%’,保证keyreads / keyreadrequests在0.1%以下最好
innodbbufferpool_size
缓存数据块和索引块,对InnoDB表性能影响最大。通过查询show status like ‘Innodbbufferpoolread%’,
保证 (Innodbbufferpoolreadrequests – Innodbbufferpoolreads)/ Innodbbufferpoolreadrequests 越高越好
innodbadditionalmempoolsize
InnoDB存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,当数据库对象非常多的时候,适当调整该参数的大小以确保所有数据都能存放在内存中提高访问效率,
当过小的时候,MySQL会记录Warning信息到数据库的错误日志中,这时就需要该调整这个参数大小
innodblogbuffer_size
InnoDB存储引擎的事务日志所使用的缓冲区,一般来说不建议超过32MB
querycachesize
缓存MySQL中的ResultSet,也就是一条SQL语句执行的结果集,所以仅仅只能针对select语句。当某个表的数据有任何任何变化,
都会导致所有引用了该表的select语句在Query Cache中的缓存数据失效。所以,当我们的数据变化非常频繁的情况下,使用Query Cache可能会得不偿失。
根据命中率(Qcachehits/(Qcachehits+Qcache_inserts)*100))进行调整,一般不建议太大,256MB可能已经差不多了,大型的配置型静态数据可适当调大.
可以通过命令show status like 'Qcache_%'查看目前系统Query catch使用大小
readbuffersize
MySql读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。
如果对表的顺序扫描请求非常频繁,可以通过增加该变量值以及内存缓冲区大小提高其性能
sortbuffersize
MySql执行排序使用的缓冲大小。如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。
如果不能,可以尝试增加sortbuffersize变量的大小
readrndbuffer_size
MySql的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,
MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。
但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
record_buffer
每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,可能想要增加该值
threadcachesize
保存当前没有与连接关联但是准备为后面新的连接服务的线程,可以快速响应连接的线程请求而无需创建新的
table_cache
类似于threadcachesize,但用来缓存表文件,对InnoDB效果不大,主要用于MyISAM
SQL三范式
第一范式(1NF)
在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。(出现重复的属性,重新定义一个实体,建立一对多的关系)如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。
2 第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。
3 第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求(在一对多关系里面,除了主键不要再另外存别的信息)一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。
湖仓一体电商项目:项目背景和架构介绍
文章目录
项目背景和架构介绍
一、项目背景介绍
湖仓一体实时电商项目是基于某宝商城电商项目的电商数据分析平台,本项目在技术方面涉及大数据技术组件搭建,湖仓一体分层数仓设计、实时到离线数据指标分析及数据大屏可视化,项目所用到的技术组件都从基础搭建开始,目的在于湖仓一体架构中数据仓库与数据湖融合打通,实现企业级项目离线与实时数据指标分析。在业务方面目前暂时涉及到会员主题与商品主题,分析指标有用户实时登录信息分析、实时浏览pv/uv分析、实时商品浏览信息分析、用户积分指标分析,后续还会继续增加业务指标和完善架构设计。
二、项目架构
1、实时数仓现状
当前基于Hive的离线数据仓库已经非常成熟,随着实时计算引擎的不断发展以及业务对于实时报表的产出需求不断膨胀,业界最近几年就一直聚焦并探索于实时数仓建设。根据数仓架构演变过程,在Lambda架构中含有离线处理与实时处理两条链路,其架构图如下:
正是由于两条链路处理数据导致数据不一致等一些列问题所以才有了Kappa架构,Kappa架构如下:
Kappa架构可以称为真正的实时数仓,目前在业界最常用实现就是Flink + Kafka,然而基于Kafka+Flink的实时数仓方案也有几个非常明显的缺陷,所以在目前很多企业中实时数仓构建中经常使用混合架构,没有实现所有业务都采用Kappa架构中实时处理实现。Kappa架构缺陷如下:
- Kafka无法支持海量数据存储。对于海量数据量的业务线来说,Kafka一般只能存储非常短时间的数据,比如最近一周,甚至最近一天。
- Kafka无法支持高效的OLAP查询,大多数业务都希望能在DWD\\DWS层支持即席查询的,但是Kafka无法非常友好地支持这样的需求。
- 无法复用目前已经非常成熟的基于离线数仓的数据血缘、数据质量管理体系。需要重新实现一套数据血缘、数据质量管理体系。
- Kafka不支持update/upsert,目前Kafka仅支持append。实际场景中在DWS轻度汇聚层很多时候是需要更新的,DWD明细层到DWS轻度汇聚层一般会根据时间粒度以及维度进行一定的聚合,用于减少数据量,提升查询性能。假如原始数据是秒级数据,聚合窗口是1分钟,那就有可能产生某些延迟的数据经过时间窗口聚合之后需要更新之前数据的需求。这部分更新需求无法使用Kafka实现。
所以实时数仓发展到现在的架构,一定程度上解决了数据报表时效性问题,但是这样的架构依然存在不少问题,Kappa架构除了以上所说的问题之外,实时业务需求多的公司在选择Kappa架构后,也避免不了一些离线数据统一计算的场景,针对Kappa架构往往需要再针对某层Kafka数据重新编写实时程序进行统一计算,非常不方便。
随着数据湖技术的出现,使Kappa架构实现批量数据和实时数据统一计算成为可能。这就是我们今天听到的“批流一体”,在业界中很多人认为批和流在开发层面上都统一到相同的SQL上处理是批流一体,也有一些人认为在计算引擎层面上批和流可以集成在同一个计算引擎是批流一体,比如:Spark/SparkStreaming/Structured Streaming/Flink框架在计算引擎层面上实现了批处理和流处理集成。
以上无论是在业务SQL使用上统一还是计算引擎上的统一,都是批流一体的一个方面,除此之外,批流一体还有一个最核心的方面就是存储层面上的统一。数据湖技术可以实现将批数据和实时数据统一存储,统一处理计算。我们可以将离线数仓中的数仓和实时数仓中的数仓数据存储统一合并到数据湖上,可以将Kappa架构中的数仓分层Kafka存储替换成数据湖技术存储,这样做到“湖仓一体”的构建。
“湖仓一体”架构构建也是目前各大公司针对离线场景和实时场景统一处理计算的方式。例如:一些大型公司使用Iceberg作为存储,那么Kappa架构中很多问题都可以得到解决,Kappa架构将变成个如下模样:
这条架构中无论是流处理还是批处理,数据存储都统一到数据湖Iceberg上,这一套结构将存储统一后,解决了Kappa架构很多痛点,解决方面如下:
- 可以解决Kafka存储数据量少的问题。目前所有数据湖基本思路都是基于HDFS之上实现的一个文件管理系统,所以数据体量可以很大。
- DW层数据依然可以支持OLAP查询。同样数据湖基于HDFS之上实现,只需要当前的OLAP查询引擎做一些适配就可以进行OLAP查询。
- 批流存储都基于Iceberg/HDFS存储之后,就完全可以复用一套相同的数据血缘、数据质量管理体系。
- 实时数据的更新。
上述架构也可以认为是Kappa架构的变种,也有两条数据链路,一条是基于Spark的离线数据链路,一条是基于Flink的实时数据链路,通常数据都是直接走实时链路处理,而离线链路则更多的应用于数据修正等非常规场景。这样的架构要成为一个可以落地的实时数仓方案、可以做到实时报表产生。
2、项目架构及数据分层
此项目中我们使用的数据湖技术是Iceberg构建“湖仓一体”架构来实时和离线分析电商业务指标。项目整体架构图如下图所示:
项目中的数据来源有两类,一是MySQL业务库数据,另一类是用户日志数据,我们通过对应的方式将两类数据首先采集到Kafka各自topic中,通过Flink处理将业务和日志数据存储在Iceberg-ODS层中,由于目前Flink基于Iceberg处理实时数据不能很好保存数据消费位置信息,所以这里同时将数据存储在Kafka中,利用Flink消费Kafka数据自动维护offset的特性来保证程序停止重启后消费数据的正确性。
整个架构是基于Iceberg构建数据仓库分层,经过Kafka处理数据都实时存储在对应的Iceberg分层中,实时数据结果经过最后分析存储在Clickhouse中,离线数据分析结果直接从Iceberg-DWS层中获取数据分析,分析结果存入MySQL中,Iceberg其它层供临时性业务分析,最终Clickhouse和MySQL中的结果通过可视化工具展示出来。
3、项目可视化效果
- 📢博客主页:https://lansonli.blog.csdn.net
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
以上是关于电商项目介绍的主要内容,如果未能解决你的问题,请参考以下文章