前台模块商品详情

sku的切换展示的模型设想

0

分析:想要实现sku动态切换展示 首先我们分析需要哪两张表

sku是在spu系列下的所以起码需要 spu的销售属性表 和 销售属性值 这两张表, 这两张表可以映射出具体需要什么

这里我们得先搞清楚

1:spu的销售属性是由电商平台定义的(一共四个:尺寸,颜色,版本,容量)存在pms_base_sale_attr表 中的

2: spu的销售属性值 销售人员自己添加的

3:sku sale attr value 是从前两张表中选出对应的销售属性值,来确定一个具体的sku

image-20210822171505197

解决A:

给你个skuId,将spu销售属性列表查出来

先将sku对应的spu查询出来

image-20210822174503501

select
 * 
from 
  pms_product_sale_attr sa,
  pms_product_sale_attr_value sav 
WHERE 
  sa.product_id =sav.product_id 
and 
  sa.sale_attr_id = sav.sale_attr_id
and
	sa.product_id = ?  可以根据skuId查询出spuId(productId)

四张:中间表

image-20210829115350369

image-20210829115936662

image-20210823150243065

image-20210823150300275

解决B:

image-20210822180325700

select
	skuId
from
	Pms_sku_sale_attr_valu ssav, 
where 
	ssav.saleAttrId in (?,?)
and
	ssav.saleAttrValueId in (?,?)

查询 出spu对应全部的销售属性值,然后根据页面的销售属性值 id查询 那就 的skuid,再根据skuid去展现具体的sku

解决的问题:1商品展现功能将两次查询 变为一次查询 ---,用hash表存每个商品属性值和对应的skuid,直接用skuid查询出具体商品

image-20210822182832893

如果按这样的来做,先根据 参数 这个是之前 根据spu查出全部的销售属性值的(销售属性1,销售属性2)查询出了skuid 然后根据skuId去查商品对象,再将商品对象展现在页面上,这样的做一个简单的查询 出现 了两次访问数据库,会对数据库带来额外的压力,不好

然后我的解决方案是:

image-20210822183810382

在第一次查询 时

image-20210822183844003

将这个商品spuid下面所有的sku 及sku的属性和属性值 全查出来

image-20210822184031773

image-20210822184109258前台

属性全部展现在页面上时,做成hash表,当你在页面上切换销售属性值 id时,就能对应出哪个skuId

然后根据前端页面的window{herf...}就可以直接去访问数据库 根据skuid 去查询

这样做根据前台选择的saleAttrValeId 直接定位 到skuId , 少去了数据库查询,性能节省了一半

功能查询商品详情得和面试官能说出来

解决的问题:2 高亮显示

从sql语句层面 解决对准显示问题,

老方案:用skuid去查询 出sku的商品,这时间sku商品的属性值 已经知道了,然后循环去对比销售属性值 ,对上了就高亮显示,比如颜色查出来的是黑色,那就对比,如果是黑色我就在前端用高亮显示,不是黑色就不显示 ,同理:其他属性也是如此

对应sql:

SELECT
	sa.*, sav.*
FROM
	pms_product_sale_attr sa
INNER JOIN 
	pms_product_sale_attr_value sav ON sa.product_id = sav.product_id
AND 
	sa.sale_attr_id = sav.sale_attr_id
AND
	sa.product_id = 97
LEFT JOIN 
	pms_sku_sale_attr_value ssav 
ON 
	sa.sale_attr_id = ssav.sale_attr_id 
and
	sav.id = ssav.sale_attr_value_id(这里有点绕,spu销售属性值表的Id,里面有很多自己之前添加的属性值 ,依次按添加顺序排出来的,id递增,   等于  中间表ssav  这张表是单个sku对应有哪些属性值 attr—value——Id)
AND 
	ssav.sku_id = 142

新方案,直接在sql层面 上就解决属性显示问题, 1 的为选中状态,0的未选中,选中的就用前端高亮下

对应sql

根据销售属性动态的切换sku功能

select
sa.,sav.,sa.id as isChecked
from
pms_product_sale_attr sa,
pms_product_sale_attr_value sav
WHERE
sa.product_id =sav.product_id
and
sa.sale_attr_id = sav.sale_attr_id
and
sa.product_id = 97

WHERE and 是内关联语句可以写成 INNER JOIN

select sa.,sav. FROM pms_product_sale_attr sa INNER JOIN pms_product_sale_attr_value sav on sa.product_id = sav.product_id AND sa.sale_attr_id = sav.sale_attr_id
where sa.product_id =97

SELECT
	sa.*, sav.*, if(ssav.sku_id,1,0) as isChecked
FROM
	pms_product_sale_attr sa
INNER JOIN 
	pms_product_sale_attr_value sav ON sa.product_id = sav.product_id
AND 
	sa.sale_attr_id = sav.sale_attr_id
AND
	sa.product_id = 97
LEFT JOIN 
	pms_sku_sale_attr_value ssav 
ON 
	sa.sale_attr_id = ssav.sale_attr_id 
and
	sav.id = ssav.sale_attr_value_id
AND 
	ssav.sku_id = 142

使用缓存redis解决页面并发的问题

基本的设计思路

image-20210830094724880

image-20210830095928303

image-20210830100018615

解决a:第三方框架整合到spring项目中 想要的技术集成第三方框架,然后整合到将这个框架类整合到spring conf配置类中,这个配置类的作用就是将这个框架类整合到spring容器中,在spirng中,类中带configuration就是配置类,启动时会扫这个类,就会到容器中来

以redis为例:

1 写个redis工厂类(连接池工厂),然后将工厂类整合到spring容器中

image-20210830100659180

mysql依赖包及jedis依赖包的理解

mysql数据库如果 你想要连接,需要用jdbc来写代码一步一步的连接上去,为了简化操作,这边apach仓库中有 个mysql的依赖,可以直接用他写好api直接连上,自己只需要写上你数据库服务器的参数即可

java连接redis数据库主要使用Jedis这么一个jar包,Jedis是Redis官方推荐的用于java访问redis的客户端,直接在pom依赖中添加即可,这个jar包中也有很多api可以让java代码直连接redis数据库

redis整合步骤:

1:加入依赖

image-20210830112602242

写一个 工具类,作用:初始化redis连接池,用这个类的方法得到jedis连接

image-20210830143343390

得到连接后没有到项目中,是起不了作用的,所以要用spring的配置类来将redis的工具类整合进容器中,

image-20210830150754527

itemcontroller下面的{skuId}.html

方法中有个skuService.getSkuId方法,查询 商品,都在这个方法下面去操作缓存 并发问题

操作如下 :

image-20210830173414765

这是基本的缓存 操作,接下来涉及到的高并发问题是要来解决的

高并发中常见的一些问题

image-20210830173554287

自己的理解 先回答下这个问题

缓存击穿:这边是对应的这个skuid被 前台在同一时间内有大量的讲求过来,如果 此时这个key的时间刚好过期,这大量的请求直接打到db上,这个就是缓存击穿 不是前台故意为之

缓存穿透:黑客利用一个没有的key在反反复复的请求,这时后台是这样处理这些请求的,一个xxx.html请求过来了,经过itemcontrller层中的skuService.getSkuId(SkuId)方法来请求,直接到了skuServiceImpl中来了,这里面实现类会将这个skuId 以定义好的redis中的key的形式去查询 下redis缓存 ,也就是这个格式,sku:xxxId:info,如果缓存 中没有,需要去查数据库 ,这时数据库 也查不到,就返回了Null, 这是第一个这样的请求,黑客会在同一时间发送大量的同样请求,这时这些请求都会出现 在同一时间查询数据库 的情况,对数据库的冲击可想而知,前台故意为之

缓存雪崩:redis中的很多key设置了相同的过期时间,在同一时间过期,请求也会在瞬间打到db(就像货物赌在仓库门口,那边 还在上货,这边出不了 ,仓库就挤炸了)不是0前台 故意为之

对应的解决方案:

缓存 击穿

缓存失效了,我们如何做到让系统正常运行,db不崩溃,

image-20210830184606301

redis设置分布式锁靠一个命令nx

这个命令的意思是想要设置一个key你需要等他不存在的时候才能设置成功,存在就设置失败

image-20210830192049576

image-20210830203720933

image-20210830203748329

image-20210830213036255

第一个请求拿到锁后,执行了db的访问,然后中间卡住了,redis中的key过期这个锁归还。 然后第二个请求拿到了这个锁,再要执行的时候,第一个请求复活了删除了这个锁, 。可以在redis中的value来设置一个uuid来确认是否是第一个请求,如果不是第一个请求,就删除一不了

image-20210830213717351

lua脚本的业务场景是删除第一个锁时,恰巧在同一时间点,在删锁的过程中,极短的时间内这个锁过期了,另个请求过来了删除了别人的锁,程序就死在了这里 , 为了防止这个问题就引用到lua脚本 ,只要得到这个locktoken查询的一瞬间就将它杀死,见到就杀掉,这样就不会出现时间差,在删除的瞬间自己的锁过期,删了别人的锁

缓存 穿透

:对应在db中查不到这个Key的时候,在缓存 中以这个skuId 设置一个固定时间空字符 串,这 样下次请求过来时,便不会打到db,

缓存 雪崩

尽量不设置相同过期的key,错开过期时间

Redisson

是什么:redis可以理解为是一个实现了很多接口的jedsi java程序框架,他有实现了juc下面的很多接口,所以他有很多juc的功能 他还实现了很多东西

怎样用到项目中:

image-20210901093954682

整合到项目中,和jedis的整合一样

原理:

image-20210901082959772

使用案例:

image-20210901084935563

会出现安全问题

redisson解决安全问题image-20210901092518002

不会出现安全问题

image-20210902081127431

自己遇到的问题3

image-20210902082343182

posted @ 2021-09-29 22:27  JargonFire  阅读(282)  评论(0)    收藏  举报