电商项目当中常见的面试题【杭州多测师_王sir】
电商项目常见的面试题
项目迭代周期?
答:项目周期为2个礼拜一个版本或者1个月一个版本。
项目团队有多少人,如何分配的?
答:项目团队由20几个人组成,2个测试,10几个人是java后台的,1-2个是前端,1个产品,1个项目经理。
你觉得做商品模块(首页展示、轮播图、购物车、单点登录、订单)时的难点在哪里?
答:商品模块:添加或者修改商品时,数据库、redis、静态页面如何同步信息。
购物车:添加的商品数量与库存数量的对比。商品价格变动同步。购物车的存储。
单点登录:如何进行多系统之间的信息交互。(主要指验证登录信息)子系统如何保证登录信息的安全。
订单:商品数量与库存的同步,商品价格的准确性。提交订单的方式,如何验证订单。
项目中前台与后台是如何进行数据交互的?
答:ajax,http请求,socket。
如何实现数据库与redis同步?
答:用消息队列mq实现。具体操作是在添加或者修改数据的时候,用mq来同步到数据库与redis,加上事务,确保reids与数据库数据一致。
项目共有多少张表?所做模块用到多少张表?表与表之间的关系?
答:180-220(选一个具体数值)
商品模块:商品表,库存表,品牌表,分类表,商品详情表,规格表,图片表,商品排序表,商品筛选表,图片资源类型表,图片资源表,商品日志表,晒单图片说明表。
购物车:商品表,品牌表,分类表,库存表,用户表,库房表,购物车表,购物项表,优惠券表,商品推荐表。
订单:订单表,用户表,用户地址表,商品表,品牌表,分类表,库存表,库房表,地区表,物流信息表。
登录(后台):用户表,权限表,角色表,用户角色表,权限角色表,日志表。
插入商品的话,要求级联插入几张表,你们当时是怎么实现的?
答:商品表,商品详情表,库存表,图片表,日志表。
生产环境与开发环境在上线部署的时候应该如何配置?
答:生产环境:
1、上线之前备份之前的项目
2、修改上线项目的相关配置
3、关停服务
4、替换之前的项目
5、启动服务,观察日志,是否异常
如何保证库存?
答:用mq+redis。
如果日志存储量过大如何处理?
答:定期清除日志,日志一般存放在另一台服务器上,15-30天清理一次。
项目的安全问题是如何解决的?
答:单点登录用token来校验。或者可以说有专门负责项目安全的人员。或者说花钱买服务。
环境安全:初期通过购买云服务
程序安全:token +签名
用户分为几种?每种所对应的权限?权限具体是如何实现的?
答:一般后天项目中普通用户、普通管理员、超级管理员。用shiro框架具体实现。
普通用户:访问。
普通管理员:管理后台信息。
超级管理员:所有权限。
商品的属性是如何进行存储的?
答:需要存储到商品表,商品详情表,库存表,日志表等。
所负责模块的查询都有那些条件?那些是静态条件、哪些是动态条件?
答:商品的价格区间,商品的品牌,商品的分类,型号,颜色,大小,男/女,商品名称。
静态条件:商品的价格区间,商品的品牌,商品的分类,型号,颜色,大小,男/女
动态条件:商品名称,商品类型
支付是如何做的?
答:与支付宝、微信对接,下载它 们两个的SDK(jar包),需要配置公钥与私钥,进行对接,根据官方文档的API,调用相关支付的借口,接收回调信息(成功或失败)。进一步做自己的业务逻辑操作。
面向服务通过什么样的方式实现?
答:soa架构,表现层与服务层分离,用dubbo和zookeeper搭配完成。
商品的审核如何做的?
答:添加或者修改,商品的价格以及库存等重要信息要进行二次填写,以保证准确率。
前台js校验,后台java代码校验。
查询商品的时候如果redis没有数据,可以抛异常么?如果不可以如何做?
答:不可以用throws抛异常,可以用trycatch捕获异常。因为在redis中查询不到数据,还要对数据库进行查询,如果throws抛异常则不能按正常业务运行。
购物车如何实现的?未登录可以用购物车么?购物车的存储?
答:购物车有三种。1.存放在Cookie。2.放在缓存里面。3.放到数据库里面。
未登录的时候可以放在cookie中,但是有的电商网站针对未登录用户不提供购物车功能。(例如天猫、淘宝添加商品到购物车的时候必须先登录)
购物车里面商品种类可以无限添加么?同一种商品的数量有限制么?
答:不可以,京东最多只可以添加八十种(足够使用了),避免占用太多存储空间,商品数量根据商品类型来控制,一般不超过200种。
如果库存数量少于购物车用户添加的数量如何处理?
答:每次用户访问购物车的时候,都发送ajax请求查询一遍redis或者数据库,如果存库数量少于购物车中商品数量,发送消息进行提示,并做相应修改。
生成订单具备的条件?如何保证这些条件?
答:商品数量不能超过限制数量和库存数量。限制数量在前台用js校验,后台查询数据库校验库存。
首页展示的轮播图,在页面中是如何存放的?在数据库中是如何存放的?
答:页面中存放的是图片地址,在数据库中存放的也是图片的地址。图片存放在另一台服务器上面。
用户地址是如何保存实现的?(具体)
答:用户的地址是单独存放在一张数据库表中的,需要绑定用户的id,还需要设置默认路径。
在电商项目中如何针对不同的用户做推送?
答:对用户的浏览内容做一下记录,然后在页面的下方或者右方做商品的推送。还有一种就是针对用户购物车或者关注商品做促销信息推送。
服务器宕机如何处理?全部宕机如何处理?
答:配置主从服务器,运维人员搭建集群后,从服务器会给主服务器发送信息,如果主服务器没有响应,那就启用从服务器。一般不会全部宕机,如果全部挂掉,就重启。
一件商品只有2件,现在被他人购买一件,这边如何修改当前用户的商品信息?
答:这个考察的是对库存的安全校验。商品上架多少库存讲库存缓存在redis 中下单就在redis 减少,异步在库存数据库中也减少商品查询只查询redis中的商品库存更新后更新redis 库存,在用户点击添加到购物车按钮时,发送ajax查询redis。
dubbo服务开发流程,运行流程?zookeeper注册中心的作用?端口是多少?
答:dubbo主要是发布服务和调用服务。
使用流程:
第一步:要在系统中使用dubbo应该先搭建一个注册中心,一般推荐使用zookeeper。
第二步:有了注册中心然后是发布服务,发布服务需要使用spring容器和dubbo标签来发布服务。并且发布服务时需要指定注册中心的位置。
第三步:服务发布之后就是调用服务。一般调用服务也是使用spring容器和dubbo标签来引用服务,这样就可以在客户端的容器中生成一个服务的代理对象,在action或者Controller中直接调用service的方法即可。
Zookeeper注册中心的作用主要就是注册和发现服务的作用。类似于房产中介的作用,在系统中并不参与服务的调用及数据的传输。
消息中间件acitveMQ的作用、原理?几种模式,每种的特点及使用问题?MQ发送消息失败怎么办?
答:Activemq的作用就是系统之间进行通信。当然可以使用其他方式进行系统间通信,如果使用Activemq的话可以对系统之间的调用进行解耦,实现系统间的异步通信。原理就是生产者生产消息,把消息发送给activemq。Activemq接收到消息,然后查看有多少个消费者,然后把消息转发给消费者,此过程中生产者无需参与。消费者接收到消息后做相应的处理和生产者没有任何关系。
Activemq有两种通信方式,点到点形式和发布订阅模式。如果是点到点模式的话,如果消息发送不成功此消息默认会保存到activemq服务端知道有消费者将其消费,所以此时消息是不会丢失的。如果是发布订阅模式的通信方式,默认情况下只通知一次,如果接收不到此消息就没有了。这种场景只适用于对消息送达率要求不高的情况。如果要求消息必须送达不可以丢失的话,需要配置持久订阅。每个订阅端定义一个id,在订阅是向activemq注册。发布消息和接收消息时需要配置发送模式为持久化。此时如果客户端接收不到消息,消息会持久化到服务端,直到客户端正常接收后为止。
Tomcat集群中怎么实现共享
答:用dubbo与zookeeper配合来实现tomcat共享。
1,tomcat自身提供的session集群共享
2,编写tomcat的session插件对session进行存储
3,使用javaweb规范中的filter对request对象的getSessio()进行拦截替换实现集群共享
Shiro如何进行权限控制?
答:1.通过浏览器访问路径,配置文件查看,是否需要认证等,如果不需要,直接访问controller
2.如果需要认证,通过配置文件的loginUrl,跳到这个地址,输入用户名、密码等
3.登录:1.访问自定义的form表单过滤器FormAuthenticationFilter(自己起的名字和shiro一样了,所以。。)的createToken方法,装配token;如果没有自定义表单过滤器,默认的FormAuthenticationFilter会自动装配表单token2.访问自定义realms的认证方法doGetAuthenticationInfo(),查库(或者缓存),判断用户名和密码是否正确。
4.如果登录之后访问的url,通过配置文件里的配置需要权限:调用自定义realms的授权方法:doGetAuthorizationInfo(),查库(或者缓存),查出用户权限,判断是否拥有权限,没权访问,跳到响应的refuse配置的路径,有权访问,跳到响应的url
Shiro的原理?分词器的原理?如何设置高亮显示?
答:Solr是基于Lucene开发的全文检索服务器,而Lucene就是一套实现了全文检索的api,其本质就是一个全文检索的过程。全文检索就是把原始文档根据一定的规则拆分成若干个关键词,然后根据关键词创建索引,当查询时先查询索引找到对应的关键词,并根据关键词找到对应的文档,也就是查询结果,最终把查询结果展示给用户的过程。
IK分析器的分词原理本质上是词典分词。现在内存中初始化一个词典,然后在分词过程中逐个读取字符,和字典中的字符相匹配,把文档中的所有的词语拆分出来的过程。
秒杀功能能否与正常的商品购买放在同一台服务器上?
答:可以,但是尽量不要这么做。因为秒杀商品,抢购的用户会比较多,并发量过高容易引起宕机,导致正常购买商品功能也不能正常使用,所以建议放在不同服务器上。
redis是内存数据库,如果宕机了,如何解决数据丢失的问题?
答:方案一:redis拥有两种不同形式的持久化方法,它们都可以用小而紧凑的格式将存储在内存中的数据写入硬盘:第一种持久化方法为时间点转储,转储操作既可以在“指定时间段内有指定数量的写操作执行”这一条件被满足时执行,又可以通过条用两条转储到硬盘中命令中的任何一条来执行;第二种持久化方法将所有修改了数据库的命令都写入一个只追加文件里面,用户可以根据数据的重要程度,将只追加写入设置为从不同步、每秒同步一次或者每写入一个命令就同步一次。
方案二:使用redis集群。Redis实现了主从复制的特性:执行复制的从服务器会连接上主服务器,接受主服务器发送的整个数据库的初始副本;之后主服务器执行的写命令,都会被发送给所有连接着的从服务器去执行,从而实时地更新从服务器的数据集。因为从服务器包含的数据会不断地进行更新,所以客户端可以向任意一个从服务器发送读请求,以此来避免对主服务器进行集中式的访问。
商品存入数据库怎么保证数据库数据安全?
答:设置后台用户的权限,并对数据库修改做好记录(日志),保证责任到人。
项目中商品小图片点开后,单品页面是大图片,这些图片是如何处理的?
答:在小图片上设置连接,点击小图片后,加载大图片。
什么是负载均衡高可用
nginx作为负载均衡器,所有请求都到了nginx,可见nginx处于非常重点的位置,如果nginx服务器宕机后端web服务将无法提供服务,影响严重。
为了屏蔽负载均衡服务器的宕机,需要建立一个备份机。主服务器和备份机上都运行高可用(High Availability)监控程序,通过传送诸如“I am alive”这样的信息来监控对方的运行状况。当备份机不能在一定的时间内收到这样的信息时,它就接管主服务器的服务IP并继续提供负载均衡服务;当备份管理器又从主管理器收到“I am alive”这样的信息时,它就释放服务IP地址,这样的主服务器就开始再次提供负载均衡服务。
什么是FastDFS
FastDFS是用c语言编写的一款开源的分布式文件系统。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
solr怎么设置搜索结果排名靠前(得分)?
可以设置文档中域的boost值,boost值越高计算出来的相关度得分就越高,排名也就越靠前。此方法可以把热点商品或者是推广商品的排名提高。
elsticsearch
1、elasticsearch了解多少,说说你们公司es的集群架构,索引数据大小,分片有多少,以及一些调优手段 。
解答:
如实结合自己的实践场景回答即可。
比如:ES集群架构13个节点,索引根据通道不同共20+索引,根据日期,每日递增20+,索引:10分片,每日递增1亿+数据,
每个通道每天索引大小控制:150GB之内。
仅索引层面调优手段:
1.1、设计阶段调优
1)根据业务增量需求,采取基于日期模板创建索引,通过roll over API滚动索引;
2)使用别名进行索引管理;
3)每天凌晨定时对索引做force_merge操作,以释放空间;
4)采取冷热分离机制,热数据存储到SSD,提高检索效率;冷数据定期进行shrink操作,以缩减存储;
5)采取curator进行索引的生命周期管理;
6)仅针对需要分词的字段,合理的设置分词器;
7)Mapping阶段充分结合各个字段的属性,是否需要检索、是否需要存储等。 …
1.2、写入调优
1)写入前副本数设置为0;
2)写入前关闭refresh_interval设置为-1,禁用刷新机制;
3)写入过程中:采取bulk批量写入;
4)写入后恢复副本数和刷新间隔;
5)尽量使用自动生成的id。
1.3、查询调优
1)禁用wildcard;
2)禁用批量terms(成百上千的场景);
3)充分利用倒排索引机制,能keyword类型尽量keyword;
4)数据量大时候,可以先基于时间敲定索引再检索;
5)设置合理的路由机制。
2、elasticsearch的倒排索引是什么?
面试官:想了解你对基础概念的认知。
解答:通俗解释一下就可以。
传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。
而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。
有了倒排索引,就能实现o(1)时间复杂度的效率检索文章了,极大的提高了检索效率。
学术的解答方式:
倒排索引,相反于一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成——词典和倒排表。
加分项:倒排索引的底层实现是基于:FST(Finite State Transducer)数据结构。
lucene从4+版本后开始大量使用的数据结构是FST。FST有两个优点:
1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;
2)查询速度快。O(len(str))的查询时间复杂度。
3、elasticsearch 索引数据多了怎么办,如何调优,部署?
面试官:想了解大数据量的运维能力。
解答:索引数据的规划,应在前期做好规划,正所谓“设计先行,编码在后”,这样才能有效的避免突如其来的数据激增导致集群处理能力不足引发的线上客户检索或者其他业务受到影响。
如何调优,正如问题1所说,这里细化一下:
4、elasticsearch是如何实现master选举的?
解答:
前置前提:
1)只有候选主节点(master:true)的节点才能成为主节点。
2)最小主节点数(min_master_nodes)的目的是防止脑裂。
这个我看了各种网上分析的版本和源码分析的书籍,云里雾里。
核对了一下代码,核心入口为findMaster,选择主节点成功返回对应Master,否则返回null。选举流程大致描述如下:
第一步:确认候选主节点数达标,elasticsearch.yml设置的值discovery.zen.minimum_master_nodes;
第二步:比较:先判定是否具备master资格,具备候选主节点资格的优先返回;若两节点都为候选主节点,则id小的值会主节点。注意这里的id为string类型。
5、详细描述一下Elasticsearch搜索的过程?
面试官:想了解ES搜索的底层原理,不再只关注业务层面了。
解答:
搜索拆解为“query then fetch” 两个阶段。
query阶段的目的:定位到位置,但不取。
步骤拆解如下:
1)假设一个索引数据有5主+1副本 共10分片,一次请求会命中(主或者副本分片中)的一个。
2)每个分片在本地进行查询,结果返回到本地有序的优先队列中。
3)第2)步骤的结果发送到协调节点,协调节点产生一个全局的排序列表。
fetch阶段的目的:取数据。
路由节点获取所有文档,返回给客户端。
6、Elasticsearch在部署时,对Linux的设置有哪些优化方法?
面试官:想了解对ES集群的运维能力。
解答:
1)关闭缓存swap;
2)堆内存设置为:Min(节点内存/2, 32GB);
3)设置最大文件句柄数;
4)线程池+队列大小根据业务需要做调整;
5)磁盘存储raid方式——存储有条件使用RAID10,增加单节点性能以及避免单节点存储故障。
7、lucence内部结构是什么?
解答:
Lucene是有索引和搜索的两个过程,包含索引创建,索引,搜索三个要点。可以基于这个脉络展开一些。
什么是sso系统
单点登录是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
登录的处理流程:
1、登录页面提交用户名密码。
2、登录成功后生成token。Token相当于原来的jsessionid,字符串,可以使用uuid。
3、把用户信息保存到redis。Key就是token,value就是TbUser对象转换成json。
4、使用String类型保存Session信息。可以使用“前缀:token”为key
5、设置key的过期时间。模拟Session的过期时间。一般半个小时。
6、把token写入cookie中。
如何判断是否登录
1.从cookie中取token
2.取不到未登录
3.取到token,到redis中查询token是否过期
4.如果过期,为登录状态
5.没有过期,登录状态
实现购车商品数据同步
1、要求用户登录。
2、把购物车商品列表保存到数据库中。推荐使用redis。
3、Key:用户id,value:购车商品列表。推荐使用hash,hash的field:商品id,value:商品信息。
4、在用户未登录情况下写cookie。当用户登录后,访问购物车列表时,
a)把cookie中的数据同步到redis。
b)把cookie中的数据删除
c)展示购物车列表时以redis为准。
d)如果redis中有数据cookie中也有数据,需要做数据合并。相同商品数量相加,不同商品添加一个新商品。
5、如果用户登录状态,展示购物车列表以redis为准。如果未登录,以cookie为准。
浏览器跨域问题
跨域是指从一个域名的网页去请求另一个域名的资源。浏览器出于安全的考虑,不允许不同源的请求
JSONP解决AJAX跨域问题:
JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
它的基本思想是,网页通过添加一个
海量数据的存储问题
如今随着互联网的发展,数据的量级也是呈指数的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。
但是,在有些场合NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。如果使用关系型数据库解决海量存储的问题呢?此时就需要做数据库集群,为了提高查询性能将一个数据库的数据分散到不同的数据库中存储。
什么是数据库分片
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果。
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。
1.一种是按照不同的表来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直切分
2.另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库上面,这种切分称之为数据的水平切分。
如何实现数据库分片
当数据库分片后,数据由一个数据库分散到多个数据库中。此时系统要查询时需要切换不同的数据库进行查询,那么系统如何知道要查询的数据在哪个数据库中?当添加一条记录时要向哪个数据库中插入呢?这些问题处理起来都是非常的麻烦。
这种情况下可以使用一个数据库中间件mycat来解决相关的问题。
什么是Mycat?
简单的说,MyCAT就是:一个新颖的数据库中间件产品,支持mysql集群,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。
Mycat读写分离
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数量取决于系统的压力,通常是1-3个读节点的配置
电商活动倒计时方案(秒杀方案):
1、确定一个基准时间。可以使用一个sql语句从数据库中取出一个当前时间。SELECT NOW();
2、活动开始的时间是固定的。
3、使用活动开始时间-基准时间可以计算出一个秒为单位的数值。
4、在redis中设置一个key(活动开始标识)。设置key的过期时间为第三步计算出来的时间。
5、展示页面的时候取出key的有效时间。Ttl命令。使用js倒计时。
6、一旦活动开始的key失效,说明活动开始。
7、需要在活动的逻辑中,先判断活动是否开始。
秒杀方案:
8、把商品的数量放到redis中。
9、秒杀时使用decr命令对商品数量减一。如果不是负数说明抢到。
10、一旦返回数值变为0说明商品已售完。
由于宜立方商城是基于SOA的架构,表现层和服务层是不同的工程。所以要实现商品列表查询需要两个系统之间进行通信。
如何实现远程通信?
1、Webservice:效率不高基于soap协议。项目中不推荐使用。
2、使用restful形式的服务:http+json。很多项目中应用。如果服务太多,服务之间调用关系混乱,需要治疗服务。
3、使用dubbo。使用rpc协议进行远程调用,直接使用socket通信。传输效率高,并且可以统计出系统之间的调用关系、调用次数。
什么是dubbo
DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案
Dubbo就是资源调度和治理中心的管理工具。
dubbo服务开发流程,运行流程?zookeeper注册中心的作用?
使用流程:
第一步:要在系统中使用dubbo应该先搭建一个注册中心,一般推荐使用zookeeper。
第二步:有了注册中心然后是发布服务,发布服务需要使用spring容器和dubbo标签来发布服务。并且发布服务时需要指定注册中心的位置。
第三步:服务发布之后就是调用服务。一般调用服务也是使用spring容器和dubbo标签来引用服务,这样就可以在客户端的容器中生成一个服务的代理对象,在action或者Controller中直接调用service的方法即可。
Zookeeper注册中心的作用主要就是注册和发现服务的作用。类似于房产中介的作用,在系统中并不参与服务的调用及数据的传输。
电商项目中是如何解决高并发和高可用的?
1.页面静态化
2.fastDFS图片服务器
3.数据缓存服务器
4.数据库集群、库表散列(数据库的各种优化、数据库的拆分)
5.负载均衡
什么是负载均衡
当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃。为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力。
我们可以建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,在让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器。如此以来,用户的每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况。
负载均衡是用反向代理的原理实现的。
redis为什么可以做缓存?项目中使用redis的目的是什么?redis什么时候使用?
1)Redis是key-value形式的nosql数据库。可以快速的定位到所查找的key,并把其中的value取出来。并且redis的所有的数据都是放到内存中,存取的速度非常快,一般都是用来做缓存使用。
2)项目中使用redis一般都是作为缓存来使用的,缓存的目的就是为了减轻数据库的压力提高存取的效率。
3)在互联网项目中只要是涉及高并发或者是存在大量读数据的情况下都可以使用redis作为缓存。当然redis提供丰富的数据类型,除了缓存还可以根据实际的业务场景来决定redis的作用。例如使用redis保存用户的购物车信息、生成订单号、访问量计数器、任务队列、排行榜等。
redis支持五种数据类型存储:1.字符串2.散列3.列表4.集合5.有序集合(问深一点可能会问道底层数据结构,以及每种数据结构常用情景)这里也可以列举一些:
应用场景
计数器
数据统计的需求非常普遍,通过原子递增保持计数。例如,点赞数、收藏数、分享数等。
排行榜
排行榜按照得分进行排序,例如,展示 近、 热、点击率 高、活跃度 高等等条件的top list。
用于存储时间戳
类似排行榜,使用redis的zset用于存储时间戳,时间会不断变化。例如,按照用户关注用户的 新动态列表。记录用户判定信息
记录用户判定信息的需求也非常普遍,可以知道一个用户是否进行了某个操作。例如,用户是否点赞、用户是否收藏、用户是否分享等。
社交列表
社交属性相关的列表信息,例如,用户点赞列表、用户收藏列表、用户关注列表等。
缓存
缓存一些热点数据,例如,PC版本文件更新内容、资讯标签和分类信息、生日祝福寿星列表。
队列
Redis能作为一个很好的消息队列来使用,通过list的lpop及lpush接口进行队列的写入和消费,本身性能较好能解决大部分问题。但是,不提倡使用,更加建议使用rabbitmq等服务,作为消息中间件。
会话缓存 使用Redis进行会话缓存。例如,将web session存放在Redis中。
业务使用方式
String(字符串): 应用数, 资讯数等, (避免了select count(*) from …)
Hash(哈希表): 用户粉丝列表, 用户点赞列表, 用户收藏列表, 用户关注列表等。
List(列表):消息队列, push/sub提醒。
SortedSet(有序集合):热门列表, 新动态列表, TopN, 自动排序。
Redis集群中,某个节点宕机怎么办?你遇见过吗?你的解决思路是什么?
redis集群:一般的是至少是2台服务器,主从服务器!如果redis集群的主服务器挂了,没有关系还有备服务器
(哨兵模式和集群模式)
中间件问题
AcitveMQ的作用、原理、特点?(生产者。消费者。 p2p、订阅实现流程)
Activemq的作用就是系统之间进行通信。当然可以使用其他方式进行系统间通信,如果使用Activemq的话可以对系统之间的调用进行解耦,实现系统间的异步通信。原理就是生产者生产消息,把消息发送给activemq。Activemq接收到消息,然后查看有多少个消费者,然后把消息转发给消费者,此过程中生产者无需参与。消费者接收到消息后做相应的处理和生产者没有任何关系。
ActiveMQ如果数据提交不成功怎么办?
Activemq有两种通信方式,点到点形式和发布订阅模式。如果是点到点模式的话,如果消息发送不成功此消息默认会保存到activemq服务端知道有消费者将其消费,所以此时消息是不会丢失的。
如果是发布订阅模式的通信方式,默认情况下只通知一次,如果接收不到此消息就没有了。这种场景只适用于对消息送达率要求不高的情况。如果要求消息必须送达不可以丢失的话,需要配置持久订阅。每个订阅端定义一个id,在订阅是向activemq注册。发布消息和接收消息时需要配置发送模式为持久化。此时如果客户端接收不到消息,消息会持久化到服务端,直到客户端正常接收后为止。
此处可能会问各种消息中间件的区别以及应用场景,即RabbitMQ、Kafka、RocketMQ之间的区别,以及里面的组件,比如我遇到过被问到RabbitMQ里面五种模式的具体写法与区别
sku的几种常用设计方法,你的sku是怎么设计的?
sku:Stock Keeping Unit(库存量单位)产品统一编号的简称,每种产品均对应有唯一的SKU号
SKU属性的设计,可以分为两类:
(1)通过属性集关联SKU属性 适合品类较少的网站,管理容易些。
(2)产品和SKU属性直接关联
适合品类很多网站,比较灵活,但是维护起来数据量比较大。
为了简化,我增加SKU属性关联产品分类(可为空,表示是全局的),这样在创建产品时,可以只列出全局的+本产品分类的SKU属性,这样就不会一下子列出很多SKU属性了。SKU属性分为前端名称和后台名称两个,方便不同业务含义的SKU属性,在前端也能够用同一个名称显示,如颜色、容量等。另外在操作上可以做些优化,比如用下拉列表显示可选的SKU属性时,可以同时显示该属性的属性描述,供产品维护人员参考。
基于SKU方式来管理产品时,产品的价格、库存和图片等信息必然是放在产品SKU表中处理的,和订单、购物车等表的关联,也是通过产品SKU表,而不是产品表。至于产品表,实际上是一个总的业务汇总和外部关联表,但实际销售的并不是它。我们网站做的更细些,会就每个产品SKU生成独立的URL(伪静态),但从SEO方面考虑,每个产品SKU拥有独立
单点登录具体实现了什么功能?
去登陆页面
提交登陆页面
用户名、密码、验证码的校验
错误信息的回显
保存用户到Session中
重定向到登陆之前的访问页面
Ajax跨域判断用户是否登陆
Redis在其中是怎么用的?起了什么作用?
redis中存储的都是key-value格式的。拿商品数据来说,key就是商品id,value是商品相关信息的json数据。
在商城系统中当并发量比较高,频繁的对数据库进行读操作的时候都需要添加缓存。例如页面中内容数据的缓存、商品数据的缓存以及用户数据的缓存等。
做商品数据的缓存时,因为商品的数据量很大,而且缓存是把数据保存到内存中,此时不可能把所有的商品数据都放到缓存中。所以需要设置商品数据缓存的有效期,当用户访问到非热点数据后,此数据放到缓存中,当缓存到期后就从缓存中删除,而且长时间不会添加到缓存。而热点数据一旦从缓存中删除会马上又添加到缓存。这样可以提高缓存的利用率,同时也减轻了数据库的压力。
关于电商项目面试遇到的问题:
1、电商项目中有没有用到多线程,哪些地方要用多线程?
2、你项目对于订单是怎么处理的,假如一个客户在下订单的时候没有购买怎么办,对于顾客在购买商品的时候你们怎么处理你们的库存?
3、计算一下133平方是多少?
4、你平时测试的流程?
5、你们数据库怎么设计的?
6、你们怎么处理redis缓存的数据,怎么删除的?
7、你觉得分布式开发的缺点是什么?
8、缓存技术你觉得在什么时候用的比较多?
9、你们怎么管理你们的内存?
10、说说你对于web前端的优化?
11、插入商品的话,要求级联插入几张表,你们当时是怎么实现的?
12、支付接口是怎么做的?
13、redis为什么可以做缓存?
14、当被问到某个模快存在安全性问题(sso单点登录系统)时,如何回答?
15、solr怎么设置搜索结果排名靠前(得分)?
16、activeMQ在项目中如何应用的?
17、activeMQ如果数据提交不成功怎么办?
1、电商项目中有没有用到多线程,哪些地方要用多线程?
项目中自己写的程序没有用到多线程,通常使用开源框架编写程序,框架中已将多线程进行了封装。
2、你项目对于订单是怎么处理的,假如一个客户在下订单的时候没有购买怎么办,对于顾客在购买商品的时候你们怎么处理你们的库存?
按照我们的理解:
如果客户在下订单的时候没有支付成功,最终订单没有完成,此商品信息还在购物车。
如果未完成的订单在一定的时间内不支付,自动取消。
如果管理库存?
对于库存的管理,我们有专门的团队负责一个进销存系统的来管理库存。
我们是在用户付款后再调用进销存系统的接口,更改库存。
3、计算一下133平方是多少?
需要详细确定题目意思?
4、你平时测试的流程?
开发过程中自己编写单元测试类对dao、service方法进行测试。
一个模块开发完成我会对模块的业务流程进行测试。
整个系统开发完成我们团队进行集成测试,测试通过后提交给测试人员
系统进行测试阶段,我会协助测试人员进行缺陷修复。
5、你们数据库怎么设计的?
先对自己负责模块的需求进行分析,搞清楚业务需求。
定义出一个一个实体(表)
根据分析的业务需求定义表的一个一个字段
分析表与表之间的关系,定义外键。
6、你们怎么处理redis缓存的数据,怎么删除的?
redis缓存的数据有一些是常驻缓存的,当数据库中数据有变化时做数据同步。
有一些缓存是设置有效期的,当缓存到期后会自动删除。
删除redis缓存使用del或者hdel命令。
7、你觉得分布式开发的缺点是什么?
1. 和集中式相比,功能之间的调用使用的是接口调用,而不是直接调用。需要编写稳定有效的API。
2. 分布式系统之间的通信无法直接通知,需要使用消息机制(MQ)进行通知。
3. 分布式开发涉及到多个开发团队,开发过程中需要频繁的进行沟通
4. 分布式开发中测试更加复杂,有效的测试用例可以帮助我们更好的剥离项目逻辑与协调组件系统。而小的集中系统开发甚至可以不使用测试用例。
5. 集中式系统开发可以使用debug从头到尾进行调试,而分布式层次太深,组件调用太多,使用debug很难整体调试。需要有效使用日志组件,更好的帮助我们找到问题。
8、缓存技术你觉得在什么时候用的比较多?
不是什么地方都需要使用缓存,符合以下两个条件才需要使用缓存。
1. 数据访问的频率很高
2. 数据修改的频率低
另外在使用缓存的时候,要注意缓存是否有效利用,需要及时清理掉缓存中不常用的数据
9、你们怎么管理你们的库存?
我们主要是负责商城功能的开发,不直接管理商品库存。
对于库存的管理,我们有专门的团队负责一个进销存系统的来管理库存
我们是在用户付款后再调用进销存系统的接口,查询商品的库存数量。如果没有库存,则付款失败并提示用户。
10、说说你对于web前端的优化?
前端是庞大的,包括 HTML、 CSS、 Javascript、Image 、Flash等等各种各样的资源。前端优化是复杂的,针对方方面面的资源都有不同的方式。那么,前端优化的目的是什么 ?
1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。
2. 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
总之,恰当的优化不仅能够改善站点的用户体验并且能够节省相当的资源利用。
前端优化的途径有很多,按粒度大致可以分为两类,第一类是页面级别的优化,例如 HTTP请求数、脚本的无阻塞加载、内联脚本的位置优化等 ;第二类则是代码级别的优化,例如 Javascript中的DOM 操作优化、CSS选择符优化、图片优化以及 HTML结构优化等等。另外,本着提高投入产出比的目的,后文提到的各种优化策略大致按照投入产出比从大到小的顺序排列
11、插入商品的话,要求级联插入几张表,你们当时是怎么实现的?
此问题主要是考察商品表设计问题:
电商网站中,商品表设计是电商的核心业务,在电商系统中占有很重要的地位:那么在商品业务系统中,保存商品表,就需要涉及很多相关表保存:
商品表涉及简单业务流程表:
1)商品分类表
2)分类属性表
3)货品表
4)货品表规格参数
5)商品表
6)品牌表
商品在保存时基本需要考虑以上几张表的关系,保存商品表必须级联保存商品属性表,同时必须保存货品表以及货品对应的规格参数表,同时必须维护商品对应的商品规格属性表
12、支付接口是怎么做的?
企业支付可以使用银联进行支付,如果使用银联进行支付,那么需要去申请,填写申请材料,获取银联提供的密钥。
企业还可以是使用第三方支付进行支付。
一般支付接口流程都大同小异。下面以支付宝为例:
接口开发最重要的应该是理解数据交互流程了,流程弄清了,并理解为何这么设计,开发起来也是事半功倍
首先,要准备下面几个参数:
企业支付宝账号的PID(也叫ParnerID)和KEY,如果使用RSA签名而不是MD5的话,还要把RSA私钥准备好支付时用户看到的东西:商品名称(subject)、支付总额(total_fee)、购买数量交易后的跳转地址,交易成功后用户可以手工点击,或页面延迟自动跳转到这个地址(return_url)交易状态异步通知地址,交易成功或交易关闭会把消息POST到这个地址(notify_url)
发起支付流程如下:
网站按照指定要求,用token和自己的私钥,构造一个重定向得到支付地址(调用支付接口)
网站把重定向地址返回给浏览器
浏览器自动重定向到该地址,即包含了token、网站签名的支付宝交易页面
支付宝显示当前交易金额、数量、卖家等信息
用户用自己的支付宝账号支付这笔金额
支付宝把用户支付成功(或失败)这个消息和订单号加上支付宝的签名,使用HTTP POST的方式通知网站(失败的话,会隔段时间重新发送)
网站处理交易后续逻辑(发货、订单状态存储之类的)
网站返回"success"字符串给支付宝,表示该通知已经处理,不用再重发
支付宝显示支付成功页面给用户(这一步和第10步是不分先后发生的)
支付成功页面延迟自动跳转,或用户点击“返回商户页面”,跳转到网站的支付结束页面(此时不一定成功处理支付宝发来的通知),但会在URL带上当前的订单号和状态。
13、redis为什么可以做缓存?
Redis就是一个高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。
第一次发送请求时,从RDBMS中获取数据并返回,同时将该数据保存分布式缓存系统中;当用户再次发送请求时直接从缓存中获取,提高性能。
14、当被问到某个模快存在安全性问题(sso单点登录系统)时,如何回答?
1、票据ticket超时
2、登录一次,所有授权的应用系统都可以访问,可能导致一些信息泄露。
3、通过cookie维护的票据ticket应该加密
4、防止cookie被伪造或者被窃取
15、solr怎么设置搜索结果排名靠前(得分)?
1、配置solr的solrconfig.xml中edismax,来改变Boost打分规则
2、或者在solr的schema中增加一个字段,该字段专门用于排序
16、activeMQ在项目中如何应用的?
答:
如何应用:activemq作为消息中间件,首先需要对activemq进行安装;其次要根据需求,分析消息的生产者和发布者;最后发送消息时,需要添加异常处理机制。
应用场景:activemq在电商项目中的应用场景比较广泛,比如索引同步、详情页静态化、商品上下架申请、调价申请、订单状态已支付后需要通知库房发货等。
17、activeMQ如果数据提交不成功怎么办?
答:该问题比较模糊,具体activemq的问题如下:
1、消费者接收消息不成功,怎么办?
对于activemq来说,如果消息生产者没有把消息发送到mq中的broker里面,则消息不会重新发送。
如果消息生产者已经把消息发送到mq中的broker里面,但是消息的消费者没有应答(可能没有接收到,也可能是接收到之后,处理业务逻辑时出现异常)。此时activemq会默认最多重发6次消息,如果依然没有接收到消息,那么该消息会进入DLQ(Dead Letter Queue死信队列)。
2、消息接收成功,但是处理出现异常,或者没有应答怎么办?
在程序中捕获异常,将消息重新放入MQ,由其它消费方再次处理。
什么是数据库分片
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果。
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。
1.一种是按照不同的表来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直切分
2.另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库上面,这种切分称之为数据的水平切分。
如何实现数据库分片
当数据库分片后,数据由一个数据库分散到多个数据库中。此时系统要查询时需要切换不同的数据库进行查询,那么系统如何知道要查询的数据在哪个数据库中?当添加一条记录时要向哪个数据库中插入呢?这些问题处理起来都是非常的麻烦。
这种情况下可以使用一个数据库中间件mycat来解决相关的问题。
什么是Mycat?
简单的说,MyCAT就是:一个新颖的数据库中间件产品,支持mysql集群,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。
Mycat读写分离
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数量取决于系统的压力,通常是1-3个读节点的配置
单点登录系统
主要解决的是Session共享的问题。
1、使用redis管理Session。
1)key:token
2)value:用户信息
3)可以需要设置有效期。
4)需要把token保存到cookie中。
购物车
1、未登录:使用cookie保存购物车数据
2、登录后:把购物车数据保存到redis。
2、购物车合并,应该以服务端的购物车为准。
电商活动倒计时方案:
1、确定一个基准时间。可以使用一个sql语句从数据库中取出一个当前时间。SELECT NOW();
2、活动开始的时间是固定的。
3、使用活动开始时间-基准时间可以计算出一个秒为单位的数值。
4、在redis中设置一个key(活动开始标识)。设置key的过期时间为第三步计算出来的时间。
5、展示页面的时候取出key的有效时间。Ttl命令。使用js倒计时。
6、一旦活动开始的key失效,说明活动开始。
7、需要在活动的逻辑中,先判断活动是否开始。
秒杀方案:
8、把商品的数量放到redis中。
9、秒杀时使用decr命令对商品数量减一。如果不是负数说明抢到。
10、一旦返回数值变为0说明商品已售完。
由于宜立方商城是基于SOA的架构,表现层和服务层是不同的工程。所以要实现商品列表查询需要两个系统之间进行通信。
如何实现远程通信?
1、Webservice:效率不高基于soap协议。项目中不推荐使用。
2、使用restful形式的服务:http+json。很多项目中应用。如果服务太多,服务之间调用关系混乱,需要治疗服务。
3、使用dubbo。使用rpc协议进行远程调用,直接使用socket通信。传输效率高,并且可以统计出系统之间的调用关系、调用次数。
什么是dubbo
DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案
Dubbo就是资源调度和治理中心的管理工具。
dubbo服务开发流程,运行流程?zookeeper注册中心的作用?
使用流程:
第一步:要在系统中使用dubbo应该先搭建一个注册中心,一般推荐使用zookeeper。
第二步:有了注册中心然后是发布服务,发布服务需要使用spring容器和dubbo标签来发布服务。并且发布服务时需要指定注册中心的位置。
第三步:服务发布之后就是调用服务。一般调用服务也是使用spring容器和dubbo标签来引用服务,这样就可以在客户端的容器中生成一个服务的代理对象,在action或者Controller中直接调用service的方法即可。
Zookeeper注册中心的作用主要就是注册和发现服务的作用。类似于×××中介的作用,在系统中并不参与服务的调用及数据的传输。
电商项目中是如何解决高并发和高可用的?
1.页面静态化
2.fastDFS图片服务器
3.数据缓存服务器
4.数据库集群、库表散列(数据库的各种优化、数据库的拆分)
5.负载均衡
什么是负载均衡
当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃。为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力。
我们可以建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,在让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器。如此以来,用户的每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况。
负载均衡是用反向代理的原理实现的。
redis为什么可以做缓存?项目中使用redis的目的是什么?redis什么时候使用?
1)Redis是key-value形式的nosql数据库。可以快速的定位到所查找的key,并把其中的value取出来。并且redis的所有的数据都是放到内存中,存取的速度非常快,一般都是用来做缓存使用。
2)项目中使用redis一般都是作为缓存来使用的,缓存的目的就是为了减轻数据库的压力提高存取的效率。
3)在互联网项目中只要是涉及高并发或者是存在大量读数据的情况下都可以使用redis作为缓存。当然redis提供丰富的数据类型,除了缓存还可以根据实际的业务场景来决定redis的作用。例如使用redis保存用户的购物车信息、生成订单号、访问量计数器、任务队列、排行榜等。
redis支持五种数据类型存储:1.字符串2.散列3.列表4.集合5.有序集合
redis集群中,某个节点宕机怎么办?你遇见过吗?你的解决思路是什么?
redis集群:一般的是至少是2台服务器,主从服务器!如果redis集群的主服务器挂了,没有关系还有备服务器
AcitveMQ的作用、原理、特点?(生产者。消费者。 p2p、订阅实现流程)
Activemq的作用就是系统之间进行通信。当然可以使用其他方式进行系统间通信,如果使用Activemq的话可以对系统之间的调用进行解耦,实现系统间的异步通信。原理就是生产者生产消息,把消息发送给activemq。Activemq接收到消息,然后查看有多少个消费者,然后把消息转发给消费者,此过程中生产者无需参与。消费者接收到消息后做相应的处理和生产者没有任何关系。
当技术面试官问到你某个技术点更深层次研究时,自己没有深入了解怎么回答?
如果没有深入研究就直接回答不知道就可以了。
特点:1.对Spring的支持2.支持多种传送协议3.完全支持jms规范
ActiveMQ在项目中如何应用的?Activemq在项目中主要是完成系统之间通信,并且将系统之间的调用进行解耦。例如在添加、修改商品信息后,需要将商品信息同步到索引库、同步缓存中的数据以及生成静态页面一系列操作。在此场景下就可以使用activemq。一旦后台对商品信息进行修改后,就向activemq发送一条消息,然后通过activemq将消息发送给消息的消费端,消费端接收到消息可以进行相应的业务处理。
插入商品的话,要求级联插入几张表,你们当时是怎么实现的?通过Redis生成商品编号(ID)
保存商品表
再保存Sku表(此表中外键,是商品表的ID)
在青岛做了两年开发,大大小小参与过三个项目的开发,一个是某公司内部的人员管理系统,一个是物流项目,最近做的是一个电商项目。
在整个项目中,我们采用的是nginx+tomcat来部署的(面试官会可能问nginx是谁来部署的?如何部署的?Nginx的执行流程,优点),nginx一方面做加载静态资源的服务器,另一方面来做反向代理和负载均衡。因为该项目需要在多个环境中运行,我们利用了nginx的反向代理解决了不同环境同系统访问地址不统一带来的问题。
因为整个项目实现的功能较多, 所以采用分布式的架构设计,整个项目包括后台管理系统、前台系统、订单系统、登录系统、搜索系统、购物车系统等,这样做的好处是使每个功能模块独立出来,降低了各系统之间的耦合度,增删一个功能不会影响其他功能模块。
因为项目是采用分布式架构设计的,各模块之间是相互独立的,而各模块的访问路径又是不同的,所以当跨域请求数据的时候会遇到跨域受限的问题。比如当用户首次访问该网站首页时,首页页面会异步请求后台管理系统加载商品的类目,这是就会出现跨域受限的问题,以前开发时,如果在本模块内,我们是通过ajax异步请求数据的,但Ajax不支持跨域,所以用ajax无法解决跨域请求数据的问题。最后我们使用的是jsonp来解决这个问题的。jsonp通过script标签的src可以跨域请求的特性,加载资源,将加载的资源(通过一个方法名将数据进行包裹)当做是js脚本解析,定义一个回调函数(是怎么实现的?),获取传入的数据。我们使用jsonp是因为Jsonp的兼容性比较好,并且在请求完毕后可以通过callback的方式回传结果。但jsonp有一个缺点是只支持get请求而不支持post等其他类型的http请求。
这样我们解决了浏览器访问当前页面去加载后台系统数据出现的跨域问题,但是另一个问题又来了,其他系统该如何得到调用后台系统的数据呐?我们想可以发送http请求来访问后台数据,我们想到的是使用httpclient来解决此问题,因为httpclient可以使用java代码模拟浏览器发送http请求(get方法如何传递参数?定义uribuilder对象,在uribuilder里设置参数,以key和value,都是string类型的,然后将uribuilder放到uri中,在后将uri讲给httpget请求。Post方法如果传输数据?模拟表单提交,将数据封装到list集合中,然后将集合数据放入构造的表单实体中,在将表单实体请求放到httppost对象中)。向外抛出一个接口,执行过程是:1、创建httpclient 对象2、构建请求对象post ,get请求3、如果有参数,就去构造请求参数
3.1 get
使用uribuilder去构造请求参数
3.2 post
构建表单实体,把表单实体放入到 post请求对象中。
4、执行请求 ,并且接受响应
5、处理响应结果
6. 释放连接。无论执行方法是否成功,都必须释放连接。
HttpClient实现认为是线程安全的。
每次连接发起Http请求的时候都会重新建立连接(经历3次握手),用完就会关闭连接(4次挥手),这样会消耗很多时间,所有我们采用了连接池。如果不采用连接池,每次连接都会打开一个端口,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接。
像项目中首页的大广告和商品类目这些不需要经常修改的数据,如果用户每次刷新页面的时候都要去数据库中查询,这样会浪费资源和增加数据库的压力。所以我们想当把这些数据添加到一个缓冲中,用户去访问的时候,先去缓存中命中,如果命中失败,再去数据库中查询,然后把查询到的数据添加到缓存中。目前比较主流的缓存技术有Redis和Memcached,单纯从缓存命中的角度来说,Memcached要高一些,可Redis和Memcache的差距其实并不大,但Redis提供的功能更加强大一些,读写速度也很快。所以我们选用了redis来缓存数据。Redis把数据以key—value的形式缓存到内存中,并提供了多种数据存储类型(string,set,list,hash等),还自身提供了持久化功能(2种),还可以把数据备份到磁盘中(Redis的SAVE命令用于创建当前 Redis 数据库的备份),防止redis宕机时的数据丢失。(会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步)。我们使用的是spring与jedis整合的客户端,可以利用jedis做分片式集群,解决了redis内存受限的问题。
之前实现的登录和注册是在同一个tomcat内部完成,而现在系统架构是每一个系统都是由一个团队进行维护,每个系统都是单独部署运行一个单独的tomcat,所以,不能将用户的登录信息保存到session中(多个tomcat的session是不能共享的)(session共享?),所以我们需要一个单独的系统来维护用户的登录信息。我们是这样做的,用户去登录页面登录,去数据库查询是否有该用户,如果没有提示用户,如果有就把用户信息保存到redis中,并生成一个token保存到cookie中,
在后台管理系统中采用了Maven的多模块化的管理,其中采用了水平切分的方式(垂直与水平划分的区别:垂直:功能模块明确,层次不够清晰,代码重用性差。水平:层次清晰,代码重用性高,独立维护。),将各层分层开发,这样做的好处是代码重用性高,层次清晰,易于独立维护。系统内部接口调用采用Httpclient,接口提供端采用RESTful方式的接口定义(一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件),系统之间的通知机制采用MQ的方式,使用RabbitMQ的实现,使用了RabbitMQ的消息订阅模式的消息机制;部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、负载均衡、另一方面是做图片等静态资源的服务器;
在此项目中我主要负责后台管理模块,主要实现商品管理和商品规格参数管理,对商品和商品规格进行CRUD操作。;在实现前台调用后台数据时,为了实现系统间的调用,便使用了httpclient技术来实现此功能,在后台提供了需要调用的接口。(httpclient介绍,工作原理,优缺点)。如果在后台对商品进行操作,为了使前台数据与后台数据实现同步,我们使用了RabbitMQ 消息队列机制实现商品同步功能(RabbitMQ介绍,工作原理,优缺点);
在此项目中,我还参与了购物车模块的开发。在开发这个模块时候,我们考虑了会员在未登录和登录两种情况下把商品加入购物车,后台如何该保存商品信息。
在用户商品详情页点击加入购物车的时候,我们用了登录拦截器来判断用户是否登录;
如果没有登录,将商品信息保存到cookie中,当用户登录后,再把商品持久到数据库中;但是考虑到cookie储存大小的问题,还有当cookie储存的数据越多就会影响响应速度,我们决定使用redis来缓存用户在未登录状态下的商品信息(redis介绍,原理,优缺点),在redis中设置缓存生存时间(如何做到的?),如果用户在规定时间内没有登录,数据便会自动删除。如果用户在规定时间内登录了,便会通过RabbitMQ消息队列机制将数据同步到数据库中