网站建设对比,专门做旅游的网站有哪些,长宁网站推广公司,高端装修公司名称0、前提引入#xff1a;
视频讲解#xff1a;
5.2-点赞功能-结合多线程定时持久化到数据库-应用redis的scan方法_哔哩哔哩_bilibili
项目前身#xff1a;
5-点赞功能-定时持久化到数据库-pipelinelua-优化ByScan_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1…0、前提引入
视频讲解
5.2-点赞功能-结合多线程定时持久化到数据库-应用redis的scan方法_哔哩哔哩_bilibili
项目前身
5-点赞功能-定时持久化到数据库-pipelinelua-优化ByScan_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1Gs4y1676q
blogLike_schedule/like05 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com)
本项目地址
本项目like05_02是like05的优化
blogLike_schedule/like05_02 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com)
https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like05_02
数据表库等注意的点
https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule
其他需要注意的点
测试时一定要将executeInternal里面的内容注释掉主要是防止定时任务的干扰 protected void executeInternal(JobExecutionContext context) throws JobExecutionException {// 要执行的内容就写在这个函数中
// blogService.updateAllLikeListToDatabase();
// blogService.updateAllLikeListToDatabaseByThreads();}1、先造一些假user数据吧:
现在是20230715-950
Slf4j
SpringBootTest
public class DataConstructTest {Resourceprivate BlogServiceImpl blogService;Autowiredprivate UserService userService;Test//获取Redis里的数据得到的是MapString, Stringpublic void addSomeUser(){for (int i 0; i 10000; i) {User user new User();user.setName(xinqi i);Long phone 10000000000L i;user.setPhone(phone.toString());userService.save(user);}}
}1.2先造假的博客数据
Test//这里不知道为什么不行
public void addSomeBlogByBatch() {long userId 0;int addCount 10000;int preCount 100;int connection addCount / preCount;for (int i 0; i connection; i) {ArrayListBlog blogs new ArrayList(preCount);for (int j 0; j preCount; j) {Blog blog new Blog();blog.setTitle(title userId);blog.setUserId(userId);}System.out.println(now userId is userId);blogService.saveBatch(blogs);}
}不知道为什么不行博客假数据的添加01.
思考应该是mybatisPlus没有配置saveBatch相关的。
将就用
Test
public void addSomeBlog() {long userId 0;for (int i 0; i 10000; i) {Blog blog new Blog();blog.setTitle(title userId);blog.setUserId(userId);System.out.println(now userId is userId);blogService.save(blog);}
}1.3win10查看、关闭和开启mysql服务
看这里吧https://blog.csdn.net/ws_please/article/details/131736814
2、先查看下redis和java服务器最大承载的内存和数据量大概是多少
这个到底要不要关心这里还是要去关系的具体可以看gitee项目里的readme文档。
2.2往redis里装载数据 Testpublic void likeBlog() {long userId 0;for (int i 4; i 10000; i) {blogService.likeBlog(userId,userId);}}
补充单线程的操作
Override
public Result updateAllLikeListToDatabaseByNoThreads() {int totalCount 0;String prefix BLOG_LIKED_KEY;Jedis jedis null;ScanParams scanParams new ScanParams();try {jedis jedisPool.getResource();String cursor 0;do {// 扫描并获取一部分keyScanResultString result jedis.scan(cursor, scanParams.match(prefix.concat(*)));//https://www.cnblogs.com/xubiao/p/8489522.html// 记录cursorcursor result.getCursor();ListString list result.getResult();totalCount list.size();if (list null || list.isEmpty()) {break;}// 遍历for (String key : list) {log.debug(key is {}, key);//这里可以看到有哪些keyMapString, String map queryAllBlogLikesUserIdWithScoresByRedisKey(key);Long blogId Long.parseLong(key.substring(prefix.length(), key.length()));durableToDatabaseByBlogIdAndMap(map, blogId);}} while (!cursor.equals(0));} catch (Exception e) {e.printStackTrace();} finally {if (jedis ! null) jedis.close();}log.debug(totalCount is {}, totalCount);return Result.ok(some like_lists had bean durable in database from cache);}接下来要来实现多线程的优化了有2种优化方式都可以各有各自的应用场景。
为什么可以用多线程来优化redis服务器是有一个容器可以装载命令的发多个命令过去可以减少网络通讯的时间MySQL也一样。
3.1优化1-多线程-等待方式
循环{通过scan扫描一部分key如果扫描的游标归0说明已经扫描结束开启线程来执行{通过这部分key在redis找到博客点赞信息再存储到数据库里面。}等待这些线程都执行完毕后再进入下一次循环。
}1、多线程-等待-的代码
GetMapping(/updateAllLikeListToDatabaseByThreads)
ApiOperation(测试多线程持久化接口)
public Result updateAllLikeListToDatabaseByThreads(){return blogService.updateAllLikeListToDatabaseByThreads();
}Overridepublic Result updateAllLikeListToDatabaseByThreads() {int totalCount 0;String prefix BLOG_LIKED_KEY;Jedis jedis null;ScanParams scanParams new ScanParams();try {jedis jedisPool.getResource();String cursor 0;do {// 扫描并获取一部分keyScanResultString result jedis.scan(cursor, scanParams.match(prefix.concat(*)));//https://www.cnblogs.com/xubiao/p/8489522.html// 记录cursorcursor result.getCursor();ListString list result.getResult();totalCount list.size();if (list null || list.isEmpty()) {break;}// ListThread threads new Vector(list.size());//对于线程的添加这里不需要用Vector因为临界区仅仅包括线程里面的内容ListThread threads new ArrayList(list.size());//用ArrayList足以// 遍历for (String key : list) {log.debug(key is {}, key);//这里可以看到有哪些keyThread t new Thread(() - {MapString, String map queryAllBlogLikesUserIdWithScoresByRedisKey(key);Long blogId Long.parseLong(key.substring(prefix.length(), key.length()));durableToDatabaseByBlogIdAndMap(map, blogId);});//这里是和like05不一样的地方 TODO postman已经测试通过了还没有对jemeter进行测试// 判断key的类型t.start();threads.add(t);}threads.forEach((t) - {try {t.join();} catch (InterruptedException e) {e.printStackTrace();}});threads null;} while (!cursor.equals(0));} catch (Exception e) {e.printStackTrace();} finally {if (jedis ! null) jedis.close();}log.debug(totalCount is {}, totalCount);return Result.ok(some like_lists had bean durable in database from cache);}也就是用了join来等待一下好处是如果风险某些线程没办法执行完毕那么可以通过threads这个ArrayList集合来拿到抛出异常对象做一些异常处理已来做一些兜底或者防护或者是补救的措施当然应该也可以执行将执行失败的线程再次通过其他方法让他重新执行直到执行成功本项目目前就没写这些内容了可以自己优化。
3.2多线程-异步
这里是因为线程创建一般默认是非守护线程因此不用join时主线程执行完毕哪怕守护线程没执行完毕后续也会继续执行下去。
//异步
Override
public Result updateAllLikeListToDatabaseByThreadsWithNoJoin() {int totalCount 0;String prefix BLOG_LIKED_KEY;Jedis jedis null;ScanParams scanParams new ScanParams();try {jedis jedisPool.getResource();String cursor 0;do {// 扫描并获取一部分keyScanResultString result jedis.scan(cursor, scanParams.match(prefix.concat(*)));//https://www.cnblogs.com/xubiao/p/8489522.html// 记录cursorcursor result.getCursor();ListString list result.getResult();totalCount list.size();if (list null || list.isEmpty()) {break;}// 遍历for (String key : list) {log.debug(key is {}, key);//这里可以看到有哪些keynew Thread(() - {MapString, String map queryAllBlogLikesUserIdWithScoresByRedisKey(key);Long blogId Long.parseLong(key.substring(prefix.length(), key.length()));durableToDatabaseByBlogIdAndMap(map, blogId);}).start();//这里是和like05不一样的地方 TODO postman已经测试通过了还没有对jemeter进行测试// 判断key的类型}} while (!cursor.equals(0));} catch (Exception e) {e.printStackTrace();} finally {if (jedis ! null) jedis.close();}log.debug(totalCount is {}, totalCount);return Result.ok(some like_lists had bean durable in database from cache);}就这样了其他的测试过程使用到了postman和jmeter这些工具具体可以看项目的README文档。
4、其他
肯定是还有其他优化空间的当然也不一定这个项目的代码没有瑕疵如果有问题可以在gitee或B站评论区提问。