前台模块商品详情
sku的切换展示的模型设想

分析:想要实现sku动态切换展示 首先我们分析需要哪两张表
sku是在spu系列下的所以起码需要 spu的销售属性表 和 销售属性值 这两张表, 这两张表可以映射出具体需要什么
这里我们得先搞清楚
1:spu的销售属性是由电商平台定义的(一共四个:尺寸,颜色,版本,容量)存在pms_base_sale_attr表 中的
2: spu的销售属性值 销售人员自己添加的
3:sku sale attr value 是从前两张表中选出对应的销售属性值,来确定一个具体的sku

解决A:
给你个skuId,将spu销售属性列表查出来
先将sku对应的spu查询出来

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)
四张:中间表




解决B:

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查询出具体商品

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

在第一次查询 时
将这个商品spuid下面所有的sku 及sku的属性和属性值 全查出来

前台
属性全部展现在页面上时,做成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解决页面并发的问题
基本的设计思路



解决a:第三方框架整合到spring项目中 想要的技术集成第三方框架,然后整合到将这个框架类整合到spring conf配置类中,这个配置类的作用就是将这个框架类整合到spring容器中,在spirng中,类中带configuration就是配置类,启动时会扫这个类,就会到容器中来
以redis为例:
1 写个redis工厂类(连接池工厂),然后将工厂类整合到spring容器中

mysql依赖包及jedis依赖包的理解
mysql数据库如果 你想要连接,需要用jdbc来写代码一步一步的连接上去,为了简化操作,这边apach仓库中有 个mysql的依赖,可以直接用他写好api直接连上,自己只需要写上你数据库服务器的参数即可
java连接redis数据库主要使用Jedis这么一个jar包,Jedis是Redis官方推荐的用于java访问redis的客户端,直接在pom依赖中添加即可,这个jar包中也有很多api可以让java代码直连接redis数据库
redis整合步骤:
1:加入依赖

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

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

itemcontroller下面的{skuId}.html
方法中有个skuService.getSkuId方法,查询 商品,都在这个方法下面去操作缓存 并发问题
操作如下 :

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

自己的理解 先回答下这个问题
缓存击穿:这边是对应的这个skuid被 前台在同一时间内有大量的讲求过来,如果 此时这个key的时间刚好过期,这大量的请求直接打到db上,这个就是缓存击穿 不是前台故意为之
缓存穿透:黑客利用一个没有的key在反反复复的请求,这时后台是这样处理这些请求的,一个xxx.html请求过来了,经过itemcontrller层中的skuService.getSkuId(SkuId)方法来请求,直接到了skuServiceImpl中来了,这里面实现类会将这个skuId 以定义好的redis中的key的形式去查询 下redis缓存 ,也就是这个格式,sku:xxxId:info,如果缓存 中没有,需要去查数据库 ,这时数据库 也查不到,就返回了Null, 这是第一个这样的请求,黑客会在同一时间发送大量的同样请求,这时这些请求都会出现 在同一时间查询数据库 的情况,对数据库的冲击可想而知,前台故意为之
缓存雪崩:redis中的很多key设置了相同的过期时间,在同一时间过期,请求也会在瞬间打到db(就像货物赌在仓库门口,那边 还在上货,这边出不了 ,仓库就挤炸了)不是0前台 故意为之
对应的解决方案:
缓存 击穿
缓存失效了,我们如何做到让系统正常运行,db不崩溃,

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



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

lua脚本的业务场景是删除第一个锁时,恰巧在同一时间点,在删锁的过程中,极短的时间内这个锁过期了,另个请求过来了删除了别人的锁,程序就死在了这里 , 为了防止这个问题就引用到lua脚本 ,只要得到这个locktoken查询的一瞬间就将它杀死,见到就杀掉,这样就不会出现时间差,在删除的瞬间自己的锁过期,删了别人的锁
缓存 穿透
:对应在db中查不到这个Key的时候,在缓存 中以这个skuId 设置一个固定时间空字符 串,这 样下次请求过来时,便不会打到db,
缓存 雪崩
尽量不设置相同过期的key,错开过期时间
Redisson
是什么:redis可以理解为是一个实现了很多接口的jedsi java程序框架,他有实现了juc下面的很多接口,所以他有很多juc的功能 他还实现了很多东西
怎样用到项目中:

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

使用案例:

会出现安全问题
redisson解决安全问题
不会出现安全问题
自己遇到的问题3


浙公网安备 33010602011771号