宜立方 电商网站 -- 问题集合
1 |基于大数据技术的电子商务平台(老师指导下完成) 2 Ø 开发时间:2017/12 – 至今 3 Ø 软件架构:Spring + SpringMVC + Mybatis +EasyUI + Solr + Redis + Maven 4 Ø 项目描述: 5 该项目采用SSM框架,采用Redis缓存,采用Solr搜索实现多维度检索,缓解访问数据库压力。采用Nginx进行地址映射、负载均衡、反向代理。并从数据存储、服务器架设、性能方面进行优化设计,对项目功能模块和系统架构进行进一步优化。采用大数据分析技术,通过对业务数据进行采集、提取、分类、分流、分析等处理,进行业务指导和决策支持。 6 项目分为:后台管理系统,前台显示系统,用户系统,订单系统等。后台管理可以实现商品分类,商品管理,广告管理等。前台系统实现显示商品分类、商品、广告等。用户系统实现注册登陆功能,订单系统实现添加购物车、商品结算功能。 7 8 描述一下这个系统: 9 [ 10 从3个方面来回答这个问题: 11 |--系统背景及系统概述 12 |--系统包括的业务模块及主业务流程 13 |--责任模块 14 ] 15 16 整体介绍: 17 1.背景及系统的概述: 18 商城是一个B2C(Business-to-Customer 商对客)电商项目,集零售与批发于一体。 19 整个项目技术用Spring,SpringMVC,Mybatis框架进行开发。 20 采用了分布式架构,使用Maven进行项目依赖和jar包的管理, 21 使用中间切分的方式将web,service,mapper,pojo分层开发,这样的好处也就是让代码的重用性更高. 22 采用Redis缓存, 23 采用Solr搜索实现多维度检索,缓解访问数据库压力, 24 采用Nginx进行地址映射、负载均衡、反向代理。 25 26 2.系统包括的业务模块及主业务流程: 27 我们的这个项目为后台商品管理模块、会员模块、订单模块、购物车模块、支付模块、搜索模块、评论模块等。 28 29 3.责任模块: 30 我在这个项目中主要负责后台商品的管理模块:主要是实现商品的录入、上下架、以及商品类目详情展示,包括 商品规格参数模板设计以及商品实际参数录入功能。其中在商品查询中没有使用传统的mybatis分页查询而是会用一个分页插件PageHelper来实现。对于商品图片的上传,在后台页面使用了富文本编辑器KindEditor进行批量上传。后台使用fileupload组件来接收图片,在后台代码里面实现图片校验功能,图片验证包括:图片大小、格式、文件内容的校验。防止危险脚本通过图片上传到服务器;文件内容的校验是通过ImageIO读取上传的文件构建BufferedImage对象,通过判定BufferedImage的宽高属性来辨别上传的文件是否为图片。关于数据库优化方面,商品表中价格字段使用long型存储,避免了开发中处理小数的问题,商品描述作为表格单独设计,因为数量比较大,而且描述一般不轻易改动,单独作为一个表在查询商品的时候不需要查询,提高了查询性能,用户需要的时候让其查询而对于商品规格参数的设计考虑一个商品对应一张表,存放该商品的规格参数数据,数据表太庞大,于是组内商讨设计了一张商品规格参数模板表,该表中有事个字段,分别是id,创建时间,更新时间、商品类目id、商品类目名称、规格参数模板数据。每个类目对应模板表的一条记录,规格参数模板数据存放的是商品类目的规格参数。新增添商品时模拟模板生成一个规格参数的表单。填写规格参数数据,保存到数据库中. 31 32 前台系统中我实现了商品分类的展示,实现商品分类展示我們当时有两种思路,第一种就是当前台系统的页面需要商品分类信息的时候,前台页面向前台系统发送ajax请求,由前台系统通过HttpClient请问后台系统获取分类信息,然后前台系统将商品分类信息数据给前台页面. 33 第二种实现方案是前台页面直接发送ajax请求访问后台系统,由于后台系统向前台页岩发送的是json格式的数据,而json数据无法进行跨域传送数据,我們当时使用了jsonp来包装json数据,实现路霸数据的传输.这种实现方案性能稍高于第一种,最后我采用了这种设计思路。 34 35 36 由于商品首页分类展示的操作很频繁,为了减轻数据库的压力,我們使用了redis作为缓存数据库。后台系统在查询mysql数据库之前,先查看redis里面是否有商品分类信息,如果有则直接返回结果,如果没有则查询mysql数据库,将查询结果保存在redis中并返回该结果。 37 38 我們的项目中关于用户登录的这块采用的是单点登录系统(什么是单点登录),考虑到一般用户登录的时候,当用户登录成功以后,我們将用户信息保存在session中,因为这个我們采用的是分布式架构,当用户登录要访问其他功能模块的时候,由于session是基于web服务器的,每一个功能模块都有自己的web服务器,各个功能模块不能共享session数据,所以用户需要重新登录.我們采用了单点登录系统.当用户登录成功后,我們根据时间戳和用户id生成唯一的令牌ticket,将ticket和用户令牌作为键值对放在redis中,并把ticket写入cookie中,当用户访问其他功能模块时,首先从cookie中拿到ticket,根据ticket在redis里面查找用户信息,如果找到则登录成功。 39 40 在首页的搜索模块中我們使用了solr实现,提供服务从数据库中查询的数据生成索引库。为了实现各模块数据之間的同步,我們在搜索模块让娃不服务接口。只要后台系统数据有增删改就调用搜索模块的服务进行索引库的维护。(搜索这一块是其他人做的,他们提供了一个接口,通过这个接口调用搜索模块的服务进行维护。) 41 42 我們使用ActivityMQ实现商品数据的同步.为了减轻数据库的压力,提高系统性能我們引入了redis缓存数据库和solr索引库,这样就会涉及一个数据同步的问题。我們要保证mysql数据库、redis缓存数据库以及索引库中商品的数据是一致的,原先我們是这么做的:当后台系统商品的数据进行增删改操作后,通过httpClient调用前台系统和搜索系统对redia和索引库进行维护.这样虽然能解决数据同步问题,但是各个模块之間的耦合性太高.当新增加某个系统以后,要对后台系统进行维护,这显然不合理的,所以我們引入了activityMQ。后台管理系统作为消息的生产者,需要发送消息,在后台系统声明交换机,确定交换机的类型topic。前端系统和搜索系统都是消息的消费者,在前端系统和搜索系统端声明队列,并监听消息,根据消息内容做出相应的操作。 43 44 购物车的实现有多种方式,可以直接使用数据库存储购买的商品信息,可以使用session来作为购物车存储商品.用数据为存储商品对数据库造成的负担特别大,而且对于购物车这种需要实时操作的东西,数据库的访问量一旦太大,数据库容易出现并发错误,或者直接崩溃.用session来存储商品信息效率确实很高,而且会話针对各个连接的,所以便于管理,但是用session也不是完美的,因为session是有有效期的,根据服务器设置不同而不同,如果你在购物的过程中session超时了,那么购物车中的东西就空了,session是保存在服务器内存中的,占用了服务器资源.session无法进行水平扩展,使用集群..基于这些我們使用cookie+Mysql,来实现购物车功能.当用户牌登录状态的时候,我們将购物车信息存放在Mysql数据库中,当用户处于离线状态,我們将购物车信息存放在cookie中,用户进行登录操作的时候,判断cookie中是否有购物车信息,如果有,则把购物车信息与数据库中的合并,因为我們使用了数据库作为购物车来存放商品数据,考虑到数据库的压力大,我們采用了数据库的集群,搭建实现数据库的读写分离.我們设计了一个主库负责写入数据,三个从库读取数据,这样就大大减轻了数据库的压力。 45 46 订单系统,购物车系统。 47 在首页的商品搜索模块我們使用了solr实现,我們提供服务从数据库中查询的数据生成索引库。为了实现与数据库之間的同步,我們在搜索快提供了服务接口。只要数据有增删改就调用对应的服务,再之后我就实现了商品详情页的展示,首先根据商品的id到redis缓存中命中,如果缓存中没有才会查询数据库,并且保存到redis中,考虑到redis是内存中的稀有资源,所以我們在设计的时候为不需要经常显示的提供了在redis中的有效时间。我們设计的是一天的时间,在商品详情页中首先将关键字段查询展示,在使用延迟的方法加载商品描述,提高了相应的速度。并且商品规格我們使用按需加载,只有点击加载商品描述,提高了生意人速度。并且商品规格我們使用按需加载,只有点击才会加载,减轻了数据库的压力。 48 49 由于顾客要创建订单需要登录,但是我們采用的是分布式架构,为了提高顾客的体验性,所以我們采用了单点登录系统。
1,电子商务常见模式
B2B:商家到商家。阿里巴巴。
B2C:商家到用户。京东。
C2C:用户到用户。淘宝。
B2B2C:商家到商家到用户。天猫。
O2O:线上到线下。美团、饿了么。
2,电子商务行业技术特点
①技术新:(NoSql推广首在社区网站和电商项目),发展快,需求推动技术的革新。
②技术范围广:除了java,像淘宝前端还使用了PHP,数据库MySQL或者oracle,nosql,服务器端使用Linux,服务器安全、系统安全
③分布式:以前是在一台机器上做运算,现在是分散到很多机器上,最后汇总起来。(集中式向分布式进行考虑)由需求来推动
④高并发、集群、负载均衡、高可用:由并发问题采用集群处理,集群会涉及服务器的主从以及分布问题,使用负载均衡。(权重高低)高可用对用户而言,用户服务不中断(系统升级,服务不中断)。
⑤海量数据:双11,570亿的背后,订单有多少?浏览次数有多少?商品会有多少?活动相关数据?
⑥业务复杂:不要简单的认为是:商品展示出来后,加入购物车后购买就完成了。后台特别复杂,比如优惠(包邮、满减)
⑦系统安全:系统上线必须通过系统安全部门审核通过。前年CSDN数据泄露。快捷酒店数据泄露(通过身份证就可以查看你的开房记录)。近几年,安全意识逐步在提高。
3,Maven是什么?为什么要进行项目依赖与Jar包管理
Maven是一个采用纯Java编写的开 源项目管理工具。采用了一种被称之为project object model (POM)概念来管理项目,所有的项目配置信息都被定义在一个叫做POM.xml的文件中,通过该文件,Maven可以管理项目的整个声明周期,包括编 译,构建,测试,发布,报告等等。Maven本身还支持多种插件,可以方便更灵活的控制项目。
Maven常用于项目构建,依赖管理,热部署等。方便Jar包管理,工程之间的依赖管理,自动打包,热部署,方便svn版本控制。
4,什么是分布式架构,为什么使用分布式架构,分布式架构的优点?
分布式结构就是将一个完整的系统,按照业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为“服务”。这些子系统能够独立运行在web容器中,它们之间通过RPC方式通信。
注:集群是多台设备干同一件事情,而分布式是不同的设备干不同的事情。
就商城项目而言。按照微服务的思想,我们需要按照功能模块拆分成多个独立的服务,如:用户服务、产品服务、订单服务、后台管理服务、数据分析服务等等。这一个个服务都是一个个独立的项目,可以独立运行。如果服务之间有依赖关系,可以通过RPC方式相互调用。
这样的好处有很多:
- 系统之间的耦合度大大降低,可以独立开发、独立部署、独立测试,系统与系统之间的边界非常明确,排错也变得相当容易,开发效率大大提升。
- 系统之间的耦合度降低,从而系统更易于扩展。我们可以针对性地扩展维护某些服务。假设这个商城要搞一次大促,下单量可能会大大提升,因此我们可以针对性地提升订单系统、产品系统的节点数量,而对于后台管理系统、数据分析系统而言,节点数量维持原有水平即可。
- 服务的复用性更高。比如,当我们将用户系统作为单独的服务后,该公司所有的产品都可以使用该系统作为用户系统,无需重复开发。
5,项目的架构,分层架构?
技术架构:本项目使用市场上较为主流的框架spring+springmvc+mybatis进行开发,采用分布式的系统架构,前台系统和单点登录系统采用了集群的方式部署,后台管理系统中采用了Maven的多模块化的管理,其中采用了水平切分的方式,将pojo、dao、service、web分层开发,这样做的好处就是可以重用性更高。系统内部接口调用采用Dubbo,在后台接口中扩展了spirng提供的jackson数据转化器实现;搜索系统使用了solr实现,在保证系统高性能的前提下,尽可能为公司节约成本,我们使用MySQL数据库进行集群(oracle收费)。在部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、负载均衡、另一方面是做图片等静态资源的服务器。
功能架构:分布式系统架构,如问题四
6,涉及的技术
Spring、SpringMVC、MybatisJSP、JSTL、jQuery、jQuery plugin、EasyUI、KindEditor(富文本编辑器)、CSS+DIV
Redis(缓存服务器)
Lucene、Solr(搜索)
httpclient(调用系统服务)
Mysql
Nginx(web服务器)
Quartz(定时任务)
RabbitMQ(消息队列)
7,功能介绍,项目实现了哪些功能?
本项目包含:前台、后台、会员、订单、搜索、单点登陆等系统模块。
1)搜索系统包括提供商品的搜索功能。
2)订单系统包括提供下单、查询订单、修改订单状态、定时处理订单。
3)后台管理系统包括管理商品、订单、类目、商品规格属性、用户管理以及内容发布等功能。
4)前台系统包括用户可以在前台系统中进行注册、登录、浏览商品、首页、下单等操作。
5)会员系统包括用户可以在该系统中查询已下的订单、收藏的商品、我的优惠券、团购等信息。
6)单点登录系统为多个系统之间提供用户登录凭证以及查询登录用户的信息。
8,为什么使用Redis缓存?使用缓存的优点?
9,使用Solr干什么?Solr怎么进行搜索的?怎么实现多维度检索?
Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。我们把搜索单独做成一个服务,可以针对该服务做扩展,做成服务集群等,其它模块都可以调用Solr服务。
10,Nginx是怎么进行地址映射,负载均衡,反向代理等工作的?
反向代理:
11,项目中数据库压力的解决方案都有哪些?还有其他的数据库压力缓解的方法吗?
1,数据库语句优化
2,数据库存储优化(双数据库切换数据分流,使用Mycat进行分表分库,Mysql进行读写分离,主备复用,主从复制)
3,数据库访问性能优化(Redis缓存数据,FastDFS数据库)
12,数据存储,服务器架设,性能方面怎么进行优化的?
数据存储:如问题11
服务器:
使用Zookeeper进行服务管理,Dubbo进行服务的发布等。
使用Spring Cloud进行服务发布,配置管理,智能路由等。
使用Nginx进行负载均衡,反向代理,区域分流。
使用FastDFS对大文件进行存储、同步、上传和下载等。
使用NoSql(Redis)做数据缓存,用空间换时间,用内存换速度。
使用Solr搜索与HBase结合实现多维度检索。
性能:
使用FreeMark进行网页静态化。
系统拆分为分布式系统,提高系统扩展性。
13,项目中遇到的问题?解决方案?
1,后台管理模块(商品录入,上架下架,商品详情展示【规格参数模板设计,实际参数录入】)
技术亮点:分页插件pagehelper,富文本编辑器,图片校验,EasyUI
数据存储优化:【商品表价格字段为long,避免小数】,【商品描述单独作为表设计】,【商品规格参数模板】
分页:
商品查询中没有使用传统的mybatis分页查询而是会用一个分页插件PageHelper来实现。
富文本编辑器:
对于商品图片的上传,在后台页面使用了富文本编辑器KindEditor进行批量上传。
图片校验:
使用fileupload组件来接收图片,在代码里面实现图片校验功能,图片验证包括:图片大小、格式、文件内容的校验。防止危险脚本上传到服务器;
文件内容的校验是通过ImageIO读取上传的文件构建BufferedImage对象,通过判定BufferedImage的宽高属性来辨别上传的文件是否为图片。
数据存储优化:
商品表中价格字段使用long型存储,避免了开发中处理小数的问题;
商品描述作为表格单独设计,因为数量比较大,而且描述一般不轻易改动,单独作为一个表在查询商品的时候不需要查询,提高了查询性能;
商品规格参数的设计考虑一个商品对应一张表,存放该商品的规格参数数据,数据表太庞大,设计了一张商品规格参数模板表;
该表中有事个字段,分别是id,创建时间,更新时间、商品类目id、商品类目名称、规格参数模板数据;
每个类目对应模板表的一条记录,规格参数模板数据存放的是商品类目的规格参数,
新增添商品时模拟模板生成一个规格参数的表单。填写规格参数数据,保存到数据库中。
2,前台技术:
技术亮点:Bootstarp,Jsonp包装json数据,页面静态化
数据库优化:Redis缓存数据库
实现商品分类展示:
第一种实现方案是:
当前台系统的页面需要商品分类信息的时候,前台页面向前台系统发送ajax请求,由前台系统通过HttpClient请问后台系统获取分类信息,
然后前台系统将商品分类信息数据给前台页面。 第二种实现方案是:
前台页面直接发送ajax请求访问后台系统,由于后台系统向前台页岩发送的是json格式的数据,而json数据无法进行跨域传送数据,
当时使用了jsonp来包装json数据,实现路霸数据的传输。
这种实现方案性能稍高于第一种,最后我采用了第二种设计思路。
3,单点登陆页面:
技术亮点:共享Session(先从Session中拿到ticket【时间戳和用户id生成的唯一令牌】,根据ticket再redis中查找用户信息)
Redis:
由于商品首页分类展示的操作很频繁,为了减轻数据库的压力,我們使用了redis作为缓存数据库。
后台系统在查询mysql数据库之前,先查看redis里面是否有商品分类信息
如果有则直接返回结果,如果没有则查询mysql数据库,将查询结果保存在redis中并返回该结果。
单点登录:
一般用户登录的时候,当用户登录成功以后,用户信息保存在session中,因为这个我們采用的是分布式架构,当用户登录要访问其他功能模块的时候,
由于session是基于web服务器的,每一个功能模块都有自己的web服务器,各个功能模块不能共享session数据,所以用户需要重新登录
我們采用了单点登录系统.当用户登录成功后,就不用在其他系统中登陆,也就是一次登陆可以获得其他所有系统的信任,
我們根据时间戳和用户id生成唯一的令牌ticket(String ticket= user.getUserId() + "" + System.currentTimeMillis();
),将ticket和用户令牌作为键值对放在redis中,并把
ticket写入cookie中,当用户访问其他功能模块时,首先从首先从cookie中拿到ticket, 根据ticket在redis里面查找用户信息,如果找到则登录成功。
4,搜索页面:
技术亮点:Solr搜索(索引库),ActivityMQ消息队列(实现数据同步【索引库,缓存与信息】),延迟加载
Solr:
在首页的搜索模块中我們使用了solr实现,提供服务从数据库中查询的数据生成索引库。为了实现各模块数据之間的同步,在搜索模块提供服务接口。
只要后台系统数据有增删改就调用搜索模块的服务进行索引库的维护。(提供了搜索服务接口,通过接口调用搜索模块的服务进行维护。)
ActivityMQ:
使用ActivityMQ实现商品数据的同步,为了减轻数据库压力,提高系统性能,引入了redis缓存数据库和solr索引库,这样就会涉及数据同步问题。
我們要保证mysql数据库、redis缓存数据库以及索引库中商品的数据是一致,
原先我們是这么做的:
当后台系统商品的数据进行增删改操作后,通过httpClient调用前台系统和搜索系统对redia和索引库进行维护.这样虽然能解决数据同步问题,
但是各个模块之間的耦合性太高.当新增加某个系统以后,要对后台系统进行维护。
这显然不合理的,所以我們引入了activityMQ。
后台管理系统作为消息的生产者,需要发送消息,在后台系统声明交换机,确定交换机的类型topic。前端系统和搜索系统都是消息的消费者,
在前端系统和搜索系统端声明队列,并监听消息,根据消息内容做出相应的操作。
5,购物车:
技术亮点:Mysql+Session存储商品信息,数据库集群(读写分离,主备复用,负载均衡)
购物车:
可以直接使用数据库存储购买的商品信息,可以使用session来作为购物车存储商品。
这样用存储商品对数据库造成的负担特别大,而且购物车这种需要实时操作的东西,数据库的访问量一旦太大,数据库容易出现并发错误,或者直接崩溃。
使用session来存储商品信息效率确实很高,而且会話针对各个连接的,所以便于管理。
但是用session也不是完美的,因为session是有有效期的,根据服务器设置不同而不同
如果你在购物的过程中session超时了,那么购物车中的东西就空了,session是保存在服务器内存中的,占用了服务器资源。
我們使用cookie+Mysql来实现。
当用户牌登录状态的时候,我們将购物车信息存放在Mysql数据库中,当用户处于离线状态,我們将购物车信息存放在cookie中,
用户进行登录操作的时候,判断cookie中是否有购物车信息,如果有,则把购物车信息与数据库中的合并,
因为我們使用了数据库作为购物车来存放商品数据,考虑到数据库的压力大,我們采用了数据库的集群,搭建实现数据库的读写分离。
我們设计了一个主库负责写入数据,三个从库读取数据,这样就大大减轻了数据库的压力。
未登录(先写到cookie和Redis缓存中,登录后写到数据库表中);
已登录(直接写到数据库,然后写到Redis缓存中)
订单系统,购物车系统。
在首页的商品搜索模块我們使用了solr实现,我們提供服务从数据库中查询的数据生成索引库。
为了实现与数据库之間的同步,我們在搜索快提供了服务接口,只要数据有增删改就调用对应的服务。
再之后我就实现了商品详情页的展示,首先根据商品的id到redis缓存中命中,如果缓存中没有才会查询数据库,并且保存到redis中,
考虑到redis是内存中的稀有资源,所以我們在设计的时候为不需要经常显示的提供了在redi中的有效时间。我們设计的是一天的时间,
在商品详情页中首先将关键字段查询展示,在使用延迟的方法加载商品描述,提高了相应的速度。
并且商品规格我們使用按需加载,只有点击加载商品描述,减轻了数据库压力