柚见(伙伴匹配系统)第六期

开发主页

  1. 开发主页(默认推荐和自己兴趣相当的用户)
  2. 优化主页的性能(缓存 + 定时任务 + 分布式锁)

前端recommend

最简单:直接 list 列表
cv searchResult页面的代码 修改
在这里插入图片描述

后端接口

在这里插入图片描述

数据内容下边距修改

在这里插入图片描述

提取用户信息卡片

便于复用组件

新建文件夹components和文件UserCardList.vue,将主页用户信息卡片提取出来。主页和用户信息搜索页进行引用。

在这里插入图片描述

<template>  <van-card v-for="user in props.userList"  :desc="user.profile"  :title="`${user.username} (${user.planetCode})`"  :thumb="user.avatarUrl"  >  <template #tags>  <van-tag plain type="danger" v-for="tag in user.tags" style="margin-right: 8px; margin-top: 8px">  {{ tag }}  </van-tag>  </template>  <template #footer>  <van-button size="mini">联系我</van-button>  </template>  </van-card></template>  <script setup lang="ts">  
import {userType} from "../assets/user";  
interface UserCardListProps{  userList:userType;  
}  const props=withDefaults(defineProps<UserCardListProps>(),{  //@ts-ignore  userList:[] as userType,  
})  </script>

使用用户信息组件

<user-card-list :user-list="userList"></user-card-list>

后台数据库存放大量数据

模拟 1000 万个用户,再去查询

  1. 用可视化界面:适合一次性导入、数据量可控
  2. 写程序:for 循环,建议分批,不要一把梭哈(可以用接口来控制)
    要保证可控、幂等,注意线上环境和测试环境是有区别的导入 1000 万条,for i 1000w
  3. 执行 SQL 语句:适用于小数据量

导入导出

可视化导出
这里自己选择导出的文件类型和导出的地方路径。(尽量用CSV,exsl格式的话因为编码因为会乱码。)

在这里插入图片描述

可视化导入

选择要导入的文件
(导入有风险,自己要想清楚用何种方式导入数据)
在这里插入图片描述

上述演示失败

使用代码导入导出数据

CPU 密集型:分配的核心线程数 = CPU - 1
IO 密集型:分配的核心线程数可以大于 CPU 核数

定时任务 && 线性插入

开启定时任务注解。
在这里插入图片描述

新建InsertUser.java

编写定时任务代码并进行测试(这里的定时取巧,尽量别用,注释掉。)
// @Scheduled(initialDelay = 5000,fixedRate = Long.MAX_VALUE )

@Component  
public class InsertUsers {  @Resource  
private UserMapper userMapper;  /**  
* 循环插入用户  
*/  
// @Scheduled(initialDelay = 5000,fixedRate = Long.MAX_VALUE )  
public void doInsertUser() {  
//统计用户执行时间  
StopWatch stopWatch = new StopWatch();  
stopWatch.start();  final int INSERT_NUM = 1000;  
for (int i = 0; i < INSERT_NUM; i++) {  
User user = new User();  
user.setUsername("模拟用户");  
user.setUserAccount("fakeUser");  
user.setAvatarUrl("https://pic.imgdb.cn/item/65b8f58d871b83018a468905.png");  
user.setProfile("我是一个假用户");  
user.setGender(0);  
user.setPassword("12345678");  
user.setUserPhone("123456789108");  
user.setEmail("shayu-yusha@qq.com");  
user.setStatus(0);  
user.setUserRole(0);  
user.setPlanetCode("931");  
user.setTags("[前端er,JavaEr]");  
userMapper.insert(user);  
}  
stopWatch.stop();  
// 输出任务执行时间  
System.out.println( stopWatch.getLastTaskTimeMillis());  }  }

for 循环插入数据的问题:

  1. 建立和释放数据库链接,每次都要访问(----批量查询解决)
  2. for 循环是绝对线性的(—并发解决 )

批量查询插入

/**  
* 循环插入用户 耗时:7260ms  
* 批量插入用户 1000 耗时: 4751ms  
*/  
@Test  
public void doInsertUser() {  
StopWatch stopWatch = new StopWatch();  
stopWatch.start();  
final int INSERT_NUM = 1000;  List<User> userList = new ArrayList<>();  
for (int i = 0; i < INSERT_NUM; i++) {  
User user = new User();  
user.setUsername("模拟用户");  
user.setUserAccount("fakeUser");  
user.setAvatarUrl("https://pic.imgdb.cn/item/65b8f58d871b83018a468905.png");  
user.setProfile("我是一个假用户");  
user.setGender(0);  
user.setPassword("12345678");  
user.setUserPhone("123456789108");  
user.setEmail("shayu-yusha@qq.com");  
user.setStatus(0);  
user.setUserRole(0);  
user.setPlanetCode("931");  
user.setTags("[前端er,JavaEr]");  
userList.add(user);  
}  
//每隔100条数据插入一次  
userService.saveBatch(userList,100);  stopWatch.stop();  
System.out.println( stopWatch.getLastTaskTimeMillis());  }

并发插入

并发执行,
这里的线程可自定义或者用idea默认的,
两种方法的区别是,自定义可以跑满线程,而默认的只能跑CPU核数-1,
代码区别:就是在异步执行处加上自定义的线程名

用户插入单元测试,注意打包时要删掉或忽略,不然打一次包就插入一次

并发要注意执行的先后顺序无所谓,不要用到非并发类的集合

自定义线程池

private ExecutorService executorService = new ThreadPoolExecutor(16, 1000, 10000, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10000));
//线程设置  
private ExecutorService executorService = new ThreadPoolExecutor(16, 1000, 10000, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10000));  /**  
* 并发批量插入用户 100000 耗时: 26830ms  
*/  
@Test  
public void doConcurrencyInsertUser() {  
StopWatch stopWatch = new StopWatch();  
stopWatch.start();  
final int INSERT_NUM = 100000;  
// 分十组  
int j = 0;  
//批量插入数据的大小  
int batchSize = 5000;  
List<CompletableFuture<Void>> futureList = new ArrayList<>();  
// i 要根据数据量和插入批量来计算需要循环的次数。  
for (int i = 0; i < INSERT_NUM/batchSize; i++) {  
List<User> userList = new ArrayList<>();  
while (true){  
j++;  
User user = new User();  
user.setUsername("模拟用户");  
user.setUserAccount("fakeUser");  
user.setAvatarUrl("https://pic.imgdb.cn/item/65b8f58d871b83018a468905.png");  
user.setProfile("我是一个假用户");  
user.setGender(0);  
user.setPassword("12345678");  
user.setUserPhone("123456789108");  
user.setEmail("shayu-yusha@qq.com");  
user.setStatus(0);  
user.setUserRole(0);  
user.setPlanetCode("931");  
user.setTags("[\"前端\",\"后端\"]"); 
userList.add(user);  
if (j % batchSize == 0 ){  
break;  
}  
}  
//异步执行,插入数据  
CompletableFuture<Void> future = CompletableFuture.runAsync(() ->{  
System.out.println("ThreadName:" + Thread.currentThread().getName());  
userService.saveBatch(userList,batchSize);  
},executorService);  
futureList.add(future);  
}  
//等待所有异步任务执行完成  
CompletableFuture.allOf(futureList.toArray(new CompletableFuture[]{})).join();  
//输出任务执行耗时  
stopWatch.stop();  
System.out.println( stopWatch.getLastTaskTimeMillis());  }

分页查询

重启项目,前端主页用户信息会刷不出来,因为数据量过大。

后端接口修改
在这里插入图片描述

(注意一下这里page的依赖是mybatis的)
添加mybatis,注意扫描的包要修改。

前端修改

在这里插入图片描述

效果

在这里插入图片描述

TODO

数据库慢?预先把数据查出来,放到一个更快读取的地方,不用再查数据库了。(缓存)

预加载缓存,定时更新缓存。(定时任务)

多个机器都要执行任务么?(分布式锁:控制同一时间只有一台机器去执行定时任务,其他机器不用重复执行了)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/478153.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11. Springboot集成Dubbo3(二)示例demo

目录 1、前言 2、注册中心 3、快速开始 3.1、添加dubbo3依赖 3.2、dubbo3-api ​编辑 3.3、dubbo3-server 3.3.1、添加依赖 3.3.2、实现IUserService 3.3.3、添加配置文件application.properties 3.3.4、修改Application启动类 3.3.5、出错解决 3.4、dubbo3-porta…

Android widget基础指南

widget的概念最早是由一名叫Rose的苹果工程师提出&#xff0c;后来经过多方面机缘巧合的发展下&#xff0c;便有了今天Android平台上的小组件widget&#xff0c;一般APP开发可能应用场景较少&#xff0c;最常见的莫过于天气APP的widget。但对于从事IOT或车载方向的同学&#xf…

【机器学习笔记】13 降维

降维概述 维数灾难 维数灾难(Curse of Dimensionality)&#xff1a;通常是指在涉及到向量的计算的问题中&#xff0c;随着维数的增加&#xff0c;计算量呈指数倍增长的一种现象。在很多机器学习问题中&#xff0c;训练集中的每条数据经常伴随着上千、甚至上万个特征。要处理这…

SpringMVC 的参数绑定之list集合、Map

标签中name属性的值就是pojo类的属性名 参数绑定4 list [对象] <form action"teaupd.do" method"post"> <c:forEach items"${list}" var"tea" varStatus "status"> 教师编号&#xff1a;<input…

微信小程序开发:appid和secret的获取方法

首先进入小程序官网 - 微信公众平台&#xff1a;https://mp.weixin.qq.com 在开发管理页即可查看 AppID。 AppSecret 需要点击生成&#xff0c;手机扫码后查看。 内容拓展&#xff1a; 当开发微信小程序时&#xff0c;了解和正确使用 AppID 和 AppSecret 是至关重要的。以…

更快找到远程/自由工作的网站

不要使用Fiver或Upwork。 它们已经饱和了。 下面是10个更快找到远程/自由工作的网站&#xff1a; 1. Toptal 这个网站专门为熟练的自由职业者提供远程工作机会&#xff0c;如Shopify和Priceline等一流公司。 他们只接受软件开发、设计和金融等领域的顶级3%自由职业者。 htt…

PyCharm 调试过程中控制台 (Console) 窗口内运行命令 - 实时获取中间状态

PyCharm 调试过程中控制台 [Console] 窗口内运行命令 - 实时获取中间状态 1. yongqiang.py2. Debugger -> Console3. Show Python PromptReferences 1. yongqiang.py #!/usr/bin/env python # -*- coding: utf-8 -*- # yongqiang chengfrom __future__ import absolute_imp…

计算机设计大赛 深度学习人体语义分割在弹幕防遮挡上的实现 - python

文章目录 1 前言1 课题背景2 技术原理和方法2.1基本原理2.2 技术选型和方法 3 实例分割4 实现效果5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习人体语义分割在弹幕防遮挡上的应用 该项目较为新颖&#xff0c;适合作为竞…

【软考问题】-- 10 - 知识精讲 - 项目风险管理

一、基本问题 1&#xff1a;按照可预测性&#xff0c;风险分哪三类&#xff1f; &#xff08;1&#xff09;已知风险&#xff1a;如项目目标不明确&#xff0c; 过分乐观的进度计划&#xff0c; 设计或施工变更和材料价格波动等。&#xff08;2&#xff09;可预测风险&#xff…

代码随想录算法训练营第三十六天|435. 无重叠区间 763.划分字母区间 56. 合并区间

435. 无重叠区间 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 细节&#xff1a; 1. 这道题目和 452.用最少数量的箭引爆气球 &#xff0c;452中的弓箭数量其实就是 无重叠区间的数量&#xff0c;用总的区间数减去 无重叠区间的数…

物骐平台双模蓝牙音频SOC按键功能验证方法

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送蓝牙音频&#xff0c;DSP音频项目核心开发资料, 概述 WQ7034AX 是一颗高规格蓝牙音频 SoC 芯片&#xff0c; 支持 BT/BLE 5.3 双模协议栈…

Java实现一个栈

目录 概念与结构 实现一个栈 创建一个栈类 实现栈的基本操作 测试栈类 概念与结构 概念与结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元…