1.根据价格升序排序并分页
select *
from tbl_menu
order by price asc
limit pageSize offset pageNum
pageSize:指定每页显示的条数
pageNum:偏移量,确定结果从哪一行开始返回
asc:升序排序
desc:降序排序
2.大数据量的情况下分库分表怎么做
1.mycat:开源的分布式数据库中间件,它将应用程序与数据库分离,提供数据库分片、读写分离、负载均衡等功能。
mycat原理是将一个逻辑数据库拆分成多个物理数据库,每个物理数据库负责一部分数据,从而实现
水平扩展和提高数据库性能
特点和原理:
(1)分片和分库分表:mycat支持将大型数据库分片成多个小型数据库,每个小型数据库叫做一个分片。每个
分片可以进一步进行分库分表,实现数据的水平划分和管理
(2)读写分离:主库写,读库查询
(3)负载均衡:将请求分发到不同的数据库实例
(4)SQL解析和路由:解析SQL语句,根据SQL中的表名和条件,将查询路由到正确的分片
(5)缓存:支持缓存查询结果
(6)事务管理:提供分布式事务管理,支持跨多个分片的事务操作
(7)SQL优化
使用mycat存储上亿条用户数据,要求可以用手机号码查询用户,要怎么做:
(1)定义分片键:这个键要是与手机号码相关的字段,比如手机号码的前缀
(2)配置分片规则:在mycat配置文件中,定义分片规则,指定如何将查询请求路由到不同的分片上。
使用分片键来计算路由规则
(3)部署分片数据库:将不同的分片部署在不同的数据库实例上。每个分片可以包含一部分用户数据,具体的
数据划分根据分片规则定义
(4)执行查询:当执行查询操作时,mycat会根据配置的路由规则将查询请求路由到相应的分片数据库上
2.sharding:一种数据库架构设计模式,用于处理大规模数据集的存储和管理。分片将数据分割成多个较小的
子集,并将每个子集存储在独立的数据库实例中
原理:
(1)数据分割:将整个数据集分割成多个分片,每个分片包含一部分数据。分片可以按照不同的方式进行划分,
如按照数据范围、哈希值、分片键等
(2)分布式存储:每个分片都存储在独立的数据库实例中,这些事例可以部署在不同的物理服务器上。
(3)路由:使用分片键来确定数据所在的分片
(4)负载均衡
(5)查询合并:当应用程序执行查询时,可能需要查询多个分片来获取完整的结果。它负责将来自不同分片的
查询结果合并成最终结果
3.spring事务的传播属性
1.REQUIRED(默认):如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的任务
2.SUPPORTS:如果当前存在事务,则加入该事务;如果不存在事务,则以非事务的方式执行
3.MANDATORY:如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常
4.REQUIRES_NEW:无论当前是否存在事务,都会创建一个新的事务。如果已经有事务存在,那么该事务会被挂起,
并在方法执行结束后再恢复
5.NOT_SUPPORTED:以非事务方式执行方法,如果当前存在事务,则挂起该事务
6.NEVER:以非事务方式执行方法,如果当前存在事务,则抛出异常
7.NESTED:如果当前存在事务,则嵌套在该事务内执行;如果不存在事务,则创建一个新的嵌套事务。
嵌套事务可以看作是原始事务内部的子事务,他有自己的保存点,并且可以独立提交和回滚。如果
外部事务提交,但内部嵌套事务回滚,那么内部嵌套事务的回滚会回滚到外部事务的保存点
8.IGNORE:无论当前是否存在事务,都会以非事务的方式执行
4.REQUIRED_NEW在什么情况下会造成死锁
方法A和方法B都使用了REQUIRED_NEW做传播属性,A和B操作数据库中相同数据行或相关数据行,此时两个不同的
线程分别访问A和B,会造成死锁
5.springboot读取yml配置文件的过程
它借助了Spring的 PropertySource 抽象来实现配置文件的加载和解析
6.springboot项目怎么实现热更新
1.springboot devtools:spring官方提供的一个开发工具,支持热部署和自动重启,在项目中添加依赖即可,
当进行代码修改保存后,springboot devtools会自动检测到并重新加载应用程序,
实现了热更新效果
2.使用热部署工具:如 springLoaded JRebel 等,来实现热更新
3.使用springcloud Config:它允许将应用程序的配置放在一个外部配置服务器中,可以动态刷新配置,
而无需重启应用
4.使用热加载类库:如 JRebel DCEVM 等,可以在运行时替换java类,实现代码的热加载和热更新
5.使用Docker容器:构建一个docker镜像,将应用程序和配置文件打包在一起,并在需要时更新docker容器,
以实现热更新
7.技术方面怎么防止短信验证码被暴力破解
1.限制尝试次数:限制每个用户每天或每小时可以尝试的验证码验证次数
2.验证码有效期:设置验证码的有效期,确保验证码在一段事件后失效
3.短信验证码缓存:将已生成的短信验证码存储在缓存中,确保同一个验证码只能验证一次。
缓存的生命周期应该与验证码的有效期一致
4.用户身份验证:在发送验证码之前,要求用户先进行身份验证,例如要求用户登录或者提供其他身份信息
5.图形验证码:使用图形验证码来替代或补充短信验证码,用户需要通过解答图形验证码来获取短信验证码
6.验证码加密:对验证码进行加密或哈希处理,以增加破解难度。在验证时,使用相同的加密方法来比较用户输入
和存储的验证码
7.IP限制:向用户发送通知,告知他们有人尝试使用他们的手机号或账号来验证验证码
8.异常检测:实施监控和日志记录,以检测异常行为,如频繁的验证码验证尝试。如果异常情况发生,
可以采取封禁IP地址或账户
9.安全库和服务:考虑使用专门的短信验证码服务提供商
8.有一个数组,数组元素20000,开启四个子线程分别累加数组的1/4,等四个子线程类加结束后,主线程再累加这四个子线程求出的和
public class GetSum {
private static final int CAPACITY = 20000;
private static final int THREADS_NUM = 4;
private static final int SIZE = CAPACITY / THREADS_NUM;
private static int[] arr = new int[CAPACITY];
public static void main(String[] args) throws InterruptedException {
for (int i = 0;i < CAPACITY;i++){
arr[i] = i + 1;
}
Thread[] threads = new Thread[THREADS_NUM];
int[] ans = new int[THREADS_NUM];
CountDownLatch latch = new CountDownLatch(THREADS_NUM);
for (int i = 0;i < THREADS_NUM;i++){
int temp = i;
threads[i] = new Thread(() -> {
int sum = 0;
int start = temp * SIZE;
int end = start + SIZE;
for (int j = start;j < end;j++){
sum += arr[j];
}
ans[temp] = sum;
latch.countDown();
});
threads[i].start();
}
latch.await();
int res = 0;
for (int x : ans){
res += x;
}
System.out.println("结果为: " + res);
}
}