Redis缓存
给数据加上缓存假设现在有如下这样一个查询数据库的方法,它简单的从数据库查询了一批数据。这个方法每次都从数据库中进行查询,如何给这些数据加上缓存,减少数据库压力,提升查询速度呢?
123456public List<Post> findAllPostByStatus(int pageNum, int pageSize, int status) { PageHelper.startPage(pageNum, pageSize); return postMapper.findAllPostByStatus(status);}
可以像下面这样进行简单的修改,查询数据库之前,先查询一次redis缓存,缓存中存在数据则直接返回缓存数据;如果缓存中没有数据则从数据库查询数据,在放入缓存。
12345678910111213141516171819public List<Post> findAllPostByStatus(int pageNum, ...
JUC并发编程(二)
线程池为什么需要线程池Java 添加线程池工具是为了:
问题
线程池的解决方案
带来的好处
频繁创建/销毁线程开销大
线程复用
提升性能,降低资源消耗
线程创建导致延迟
预创建线程
提高响应速度
无限制创建线程风险高
统一管理,控制数量
提高系统稳定性和可管理性
功能单一
提供定时、拒绝策略等
增强功能性和健壮性
因此,线程池是构建高性能、高稳定性、可管理多线程应用程序的核心基础和必备工具。在 Java 中,java.util.concurrent 包下的线程池框架是并发编程的基石,几乎在所有需要处理并发任务的服务器端应用中都会用到。
线程池的创建方法Java 中线程池的创建方式主要有两大类:
通过 Executors 工厂类(快速创建):提供了几种预设的线程池配置,方便快捷,适用于常见场景。
通过 ThreadPoolExecutor 构造函数(手动创建):提供了所有可配置参数,允许开发者进行更精细化的控制,这是《阿里巴巴Java开发手册》等规范推荐的方式,以避免使用Executors可能带来的风险。
方式一:使用Executors工厂类Executo ...
JUC并发编程(一)
JUC概述JUC是什么JUC 是 Java 中处理多线程编程的一个工具包(java.util.concurrent 包),提供了一套强大的工具,让开发者能更轻松、安全地编写高性能的多线程程序。
进程 线程 协程进程(Process)进程是操作系统进行资源分配和调度的基本单位。它是一个正在执行的程序的实例,拥有独立的地址空间、代码、数据和系统资源(如文件句柄、网络端口等)。
可以简单理解为资源+线程,操作系统运行的一个程序。
线程(Thread)线程是进程内的执行单元,是CPU调度和执行的基本单位。一个进程可以包含多个线程,所有线程共享进程的地址空间和资源。
比如一个程序通过一个个线程对CPU进行调度。
协程(Coroutine / Fiber)协程是用户态的轻量级线程,由程序员在用户空间管理调度(而非操作系统内核)。协程在同一个线程内执行,通过协作式调度(非抢占式)来切换执行流。
总结
先有进程,然后进程可以创建线程,线程是依附在进程里面的,线程里面可以包含多个协程。
进程之间不共享资源,所有的线程共享进程的资源,协程共享线程的资源。
串行 并发 并行串行(Serial)串行执行是指 ...
MySql InnoDB页结构
一、什么是页页是 InnoDB 中磁盘管理的最小单位,所有对数据的读写操作,最终都是基于页来进行的。InnoDB每次从磁盘中读取数据到内存都是以也为单位进行。
默认大小:16KB。这是在 MySQL 编译或初始化时确定的,通常不建议修改。
作用:它是数据在磁盘和内存(Buffer Pool)之间传输的基本单元。也就是说,从磁盘读取数据到内存,或者从内存刷新数据到磁盘,都是以整个页为单位来操作的。
二、为什么需要页如果没有页这个概念,数据库每次都需要读写精确的字节,这将导致极低的 I/O 效率。通过将数据组织成固定大小的页:
提高 I/O 效率:磁盘的顺序读写远快于随机读写。一次读写 16KB 的数据比多次读写几个字节要高效得多。
简化内存管理:InnoDB 的主要内存结构缓冲池(Buffer Pool) 就是由一个个 16KB 的页帧(Frame)组成的,每个帧正好可以存放一个从磁盘读上来的页。这使得内存管理变得非常简单和统一。
组织数据:页是更高层级数据结构(如索引、表空间)的构建块。
三、页的内部结构一个 16KB 的页并不是全部用来存放用户数据的,它被划分成多个部分,各有 ...
RocketMQ学习(二)
SpringBoot整合RocketMQ1.添加maven依赖12345<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.3.4</version></dependency>
2.添加配置1234rocketmq: name-server: "127.0.0.1:9876" producer: group: "MyTestGroup"
3.创建RocketMQTemplate可以直接用spring boot已经实例化好的template
12@Resourceprivate RocketMQTemplate rocketMQTemplate;
也可以自己创建一个template
123@ExtRocketMQTemplateConfigu ...
RocketMQ学习(一)
一、MQ简介1.什么是消息队列(MQ)?消息队列是一种异步的进程间通信(IPC)方式。它本质上是一个存储在内核或独立进程(如RabbitMQ、Kafka等)中的队列(先进先出的数据结构)。
它的基本模型很简单,通常包含两个角色:
生产者(Producer):负责创建消息并发送到消息队列。
消费者(Consumer):负责从消息队列中获取消息并进行处理。
消息(Message)就是在生产者和消费者之间传输的数据,可以是任何格式,如JSON、XML、纯文本等。
2.主要作用:解耦、异步、削峰消息队列的核心价值可以通过三个关键词来理解:
解耦(Decoupling)
问题:在传统同步调用中,服务A调用服务B,如果服务B宕机或修改接口,服务A会直接失败或需要跟着修改。服务之间是紧耦合的。
MQ的解决方案:服务A只需要将消息发送到MQ,就认为任务完成了,不需要知道由谁、何时来处理。服务B也只需要从MQ中取消息处理,不需要知道消息来自哪里。这样,服务A和服务B就完全解耦了,可以独立开发、部署和扩展。
异步(Asynchronous)
问题:同步调用中,服务A调用服务B,必须等待服务B处理 ...
SpringBoost项目使用JavaMailSender发送邮件
导入依赖12345<!-- springboot 邮件支持 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId></dependency>
ymal配置12345678spring: mail: host: ${MAIL_HOST:smtp.qq.com} port: ${MAIL_port:465} protocol: ${MAIL_PROTOCOL:smtps} default-encoding: UTF-8 username: ${MAIL_USERNAME:xxx@qq.com} password: ${MAIL_PASSWORD:}
...
服务器常用命令整理
常用命令清空屏幕1clear
端口占用1lsof -i:端口号
1netstat -tunlp |grep 端口号
后台运行jar包1nohup java -jar xxx.jar &
nginx启动
1/usr/local/nginx/sbin/nginx
1/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
重新加载配置
1234#进入nginx目录cd /usr/local/nginx/sbin#执行重载命令./nginx -s reload
关闭
123456#进入nginx目录cd /usr/local/nginx/sbin# 快速停止nginx./nginx -s stop# 完整有序的停止nginx,这个命令会等待所有请求结束后再关闭nginx./nginx -s quit
防火墙启动
1systemctl start firewalld
关闭
1systemctl stop firewalld
查看状态
1systemctl status firewalld
开 ...
Sentinel使用方法
快速开始参考Sentinel官方文档的快速开始。
引入依赖12345<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.5</version></dependency>
自定义资源
资源 是 Sentinel 中的核心概念之一。最常用的资源是我们代码中的 Java 方法。 当然,您也可以更灵活的定义你的资源。
1234567891011121314public void sentinelTest2(int i) { try (Entry entry = SphU.entry("sentinelTest1")) { // 被保护的逻辑 log.info(i + ""); } catch (BlockException ...
SpringAOP切点标记为注解
AOP切入点通过AOP提供的切入点表达式,我们除了能在类,方法等位置指定切入点,还能在注解位置加入切入点。这样在我们添加注解的位置就会执行切面方法。
自定义注解1234567891011@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface SystemLog { String actionType(); String actionDescription(); String functionName();}
定义一个切入点123@Pointcut(value = "@annotation(com.fizzy.core.annotation.SystemLog)")private void logPointcut() {}
定义一个切面方法123456789101112131415161718192021222324252627@Before(& ...