-
第八章 分布缓存实战-List-Hash数据结构最佳案例实战
第1集 在线教育-天热销视频榜单实战-List数据结构设计
简介:在线教育-天热销视频榜单实战-List数据结构设计
-
需求
- 小滴课堂官网需要一个视频学习榜单,每天更新一次
- 需要支持人工运营替换榜单位置
-
企业中流程
- 定时任务计算昨天最多人学习的视频
- 晚上12点到1点更新到榜单上
- 预留一个接口,支持人工运营
-
类似场景
- 京东:热销手机榜单、电脑榜单等
- 百度:搜索热榜
-
疑惑:为啥不是实时计算,真正高并发下项目,都是预先计算好结果,然后直接返回数据,且存储结构最简单
第2集 在线教育-天热销视频榜单实战-编码最佳实践
简介:在线教育-天热销视频榜单实战-编码最佳实践
- 开发接口
@RequestMapping("rank")
public JsonData videoRank(){
List<VideoDO> list = redisTemplate.opsForList().range(RANK_KEY,0,-1);
return JsonData.buildSuccess(list);
}
- 测试数据
@Test
void saveRank(){
String RANK_KEY = "rank:video";
VideoDO video1 = new VideoDO(3,"PaaS工业级微服务大课","xdclass.net",1099);
VideoDO video2 = new VideoDO(5,"AlibabaCloud全家桶实战","xdclass.net",59);
VideoDO video3 = new VideoDO(53,"SpringBoot2.X+Vue3综合实战","xdclass.net",49);
VideoDO video4 = new VideoDO(15,"玩转23种设计模式+最近实战","xdclass.net",49);
VideoDO video5 = new VideoDO(45,"Nginx网关+LVS+KeepAlive","xdclass.net",89);
redisTemplate.opsForList().leftPushAll(RANK_KEY,video4,video5,video3,video2,video1);
}
- 人工运营操作榜单
/**
* 替换榜单第二名
*/
@Test
void replaceRank(){
String RANK_KEY = "rank:video";
VideoDO video = new VideoDO(42,"小滴课堂面试专题第一季高级工程师","xdclass.net",89);
//在集合的指定位置插入元素,如果指定位置已有元素,则覆盖,没有则新增
redisTemplate.opsForList().set(RANK_KEY,1,video);
}
第3集 自营电商平台-购物车实现案例-Hash数据结构最佳实践
简介:自营电商平台-购物车实现案例-Hash数据结构最佳实践
-
背景
- 电商购物车实现,支持买多件商品,每个商品可以买不同数量
- 支持高性能处理
-
购物车常见实现方式
-
实现方式一:存储到数据库
- 性能存在瓶颈
-
实现方式二:前端本地存储-localstorage-sessionstorage
- localstorage在浏览器中存储 key/value 对,没有过期时间。
- sessionstorage在浏览器中存储 key/value 对,在关闭会话窗口后将会删除这些数据。
-
实现方式三:后端存储到缓存如redis
- 可以开启AOF持久化防止重启丢失(推荐)
-
-
购物车数据结构介绍
-
一个购物车里面,存在多个购物项
-
所以 购物车结构是一个双层Map:
- Map<String,Map<String,String>>
- 第一层Map,Key是用户id
- 第二层Map,Key是购物车中商品id,值是购物车数据
-
-
对应redis里面的存储
- redis里面有多种数据结构,应该使用哪种?
- 答案是 hash结构
第4集 高并发下的互联网电商购物车实战-相关VO类和数据准备
简介:高并发下的互联网电商购物车实战-相关VO类和数据准备
- VideoDO类
- CartItemVO
public class CartItemVO {
/**
* 商品id
*/
private Integer productId;
/**
* 购买数量
*/
private Integer buyNum;
/**
* 商品标题
*/
private String productTitle;
/**
* 图片
*/
private String productImg;
/**
* 商品单价
*/
private int price ;
/**
* 总价格,单价+数量
*/
private int totalPrice;
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public Integer getBuyNum() {
return buyNum;
}
public void setBuyNum(Integer buyNum) {
this.buyNum = buyNum;
}
public String getProductTitle() {
return productTitle;
}
public void setProductTitle(String productTitle) {
this.productTitle = productTitle;
}
public String getProductImg() {
return productImg;
}
public void setProductImg(String productImg) {
this.productImg = productImg;
}
/**
* 商品单价 * 购买数量
* @return
*/
public int getTotalPrice() {
return this.price*this.buyNum;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public void setTotalPrice(int totalPrice) {
this.totalPrice = totalPrice;
}
}
- CartIVO
public class CartVO {
/**
* 购物项
*/
private List<CartItemVO> cartItems;
/**
* 购物车总价格
*/
private Integer totalAmount;
/**
* 总价格
* @return
*/
public int getTotalAmount() {
return cartItems.stream().mapToInt(CartItemVO::getTotalPrice).sum();
}
public List<CartItemVO> getCartItems() {
return cartItems;
}
public void setCartItems(List<CartItemVO> cartItems) {
this.cartItems = cartItems;
}
}
- 数据源层
@Repository
public class VideoDao {
private static Map<Integer,VideoDO> map = new HashMap<>();
static {
map.put(1,new VideoDO(1,"工业级PaaS云平台+SpringCloudAlibaba 综合项目实战(完结)","https://xdclass.net",1099));
map.put(2,new VideoDO(2,"玩转新版高性能RabbitMQ容器化分布式集群实战","https://xdclass.net",79));
map.put(3,new VideoDO(3,"新版后端提效神器MybatisPlus+SwaggerUI3.X+Lombok","https://xdclass.net",49));
map.put(4,new VideoDO(4,"玩转Nginx分布式架构实战教程 零基础到高级","https://xdclass.net",49));
map.put(5,new VideoDO(5,"ssm新版SpringBoot2.3/spring5/mybatis3","https://xdclass.net",49));
map.put(6,new VideoDO(6,"新一代微服务全家桶AlibabaCloud+SpringCloud实战","https://xdclass.net",59));
}
/**
* 模拟从数据库找
* @param videoId
* @return
*/
public VideoDO findDetailById(int videoId) {
return map.get(videoId);
}
}
- json工具类
public class JsonUtil {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param clazz 对象中的object类型
* @return
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
第5集 高并发下的互联网电商购物车实战-加入购物车接口开发
简介:电商购物车实现案例-加入购物车接口开发
- 添加购物车接口
@RequestMapping("addCart")
public JsonData addCart(int videoId,int buyNum){
//获取购物车
BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
Object cacheObj = myCart.get(videoId+"");
String result = "";
if (cacheObj != null) {
result = (String) cacheObj;
}
if (cacheObj == null) {
//不存在则新建一个购物项
CartItemVO cartItem = new CartItemVO();
//从数据库查询详情,我们这边直接随机写个
VideoDO videoDO = videoDao.findDetailById(videoId);
videoDO.setId(videoId);
cartItem.setPrice(videoDO.getPrice());
cartItem.setBuyNum(buyNum);
cartItem.setProductId(videoId);
cartItem.setProductImg(videoDO.getImg());
cartItem.setProductTitle(videoDO.getTitle());
myCart.put(videoId+"", JsonUtil.objectToJson(cartItem));
} else {
//存在则新增数量
CartItemVO cartItem = JsonUtil.jsonToPojo(result, CartItemVO.class);
cartItem.setBuyNum(cartItem.getBuyNum() + buyNum);
myCart.put(videoId+"", JsonUtil.objectToJson(cartItem));
}
return JsonData.buildSuccess();
}
- 购物车方法抽取
/**
* 抽取我的购物车通用方法
*
* @return
*/
private BoundHashOperations<String, Object, Object> getMyCartOps() {
String cartKey = getCartKey();
return redisTemplate.boundHashOps(cartKey);
}
/**
* 获取购物车的key
*
* @return
*/
private String getCartKey() {
//从拦截器获取 ,这里写死即可,每个用户不一样
int userId = 88;
String cartKey = String.format("product:cart:%s", userId);
return cartKey;
}
第6集 高并发下的互联网电商购物车实战-查看和清空购物车功能开发
简介:高并发下的互联网电商购物车实战-查看和清空购物车功能开发
- 查看我的购物车
@GetMapping("/mycart")
public JsonData findMyCart(){
BoundHashOperations<String,Object,Object> myCart = getMyCartOps();
List<Object> itemList = myCart.values();
List<CartItemVO> cartItemVOList = new ArrayList<>();
for(Object item: itemList){
CartItemVO cartItemVO = JsonUtil.jsonToPojo((String)item,CartItemVO.class);
cartItemVOList.add(cartItemVO);
}
//封装成cartvo
CartVO cartVO = new CartVO();
cartVO.setCartItems(cartItemVOList);
return JsonData.buildSuccess(cartVO);
}
- 清空购物车
@GetMapping("/clear")
public JsonData clear() {
String cartKey = getCartKey();
redisTemplate.delete(cartKey);
return JsonData.buildSuccess();
}
来源:https://www.cnblogs.com/Xd17324217006/p/14921697.html
最新更新
python爬虫及其可视化
使用python爬取豆瓣电影短评评论内容
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比