1、如何解决详情页高并发访问的问题?
场景:文章详情页,商品详情页,秒杀页面
1)Freemarker静态化技术,FastDFS/MinIO/阿里OSS存储静态页面
2)流程
首先,在后台文章发布后,立即为文章生成静态页面,这里采用Freemarker结合文章模板页面生成静态页面
然后,我们把生成的文章详情静态页存储到MinIO,这样可以提高文章访问的并发量,减少详情页查询数据库的压力。
最后,用户直接访问MinIO中的静态页面,无需访问数据库
静态化技术有什么缺点?
每次文章内容修改,需要重新生成静态页面
2、说说悲观锁和乐观锁?有哪些常见的悲观锁和乐观锁?
悲观锁:当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发问题。
常见的悲观锁实现:关系数据库MySQL的行锁和表锁,Java的 synchronized 关键字,分布式锁Redisson (Redis实现)
悲观锁优点:数据更加安全,不容易出现并发问题
悲观锁缺点:高并发时对性能较大,而且可能出现死锁现象。
乐观锁:乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
常见的乐观锁实现:版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会 +1。当线程 A 要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。
用户表:tb_user
id name sex version
1 jack 男 1
select version v from tb_user where id = 1; v = 1
update tb_user set sex=’女’ where id = 1 and version = 1
乐观锁优势:并没有真正对操作加锁,对读多写少的场景性能影响小。
3、请说说MySQL表级锁和行级锁?
表级锁:对整个表记录锁定,一个事务修改表数据的时候,另一个事务无法修改表数据。
语法:
lock table tb_user read local;
update tb_user ssss
insert into tb_user
unlock;
特点:锁定范围比较大,比较影响性能
应用场景:在数据迁移场景下使用
行级锁:对表的某条(某些)记录锁定
行级锁分为 共享锁 和 排他锁
update/insert
共享锁:一个事务在修改记录的时候,另一个事务无法修改记录,但是可以读取。
update tb_user set sex=’女’ where id = 1 lock in share mode;
排他锁:一个事务在查询/修改记录的时候,另一个事务无法修改和读取数据。
select * from tb_user where id = 1 for update;
4、请说说哪些情况会导致Spring事务失效?
1)注解@Transactional配置的方法非public权限修饰
2)注解@Transactional所在类非Spring容器管理的bean
3)注解@Transactional所在类中,注解修饰的方法被本类的其他内部方法调用(建议说)
4)业务代码抛出异常类型非RuntimeException,事务失效 FileNotFoundException()
5)业务代码中存在异常时,使用try…catch…语句块捕获,而catch语句块没有throw new RuntimeExecption异常
6)注解@Transactional中Propagation属性值设置错误即Propagation.NOT_SUPPORTED(很少见)
事务传播行为 共7个,只要知道常用的这4个即可
@Transactional(propagation = Propagation.REQUIRED) 默认值,当前方法必须处在事务中。前面的业务方法有事务,同共享前面的事务;如果前面没有事务,则开启新事务
@Transactional(propagation = Propagation.SUPPORTS) 前面业务方法有事务,同共享前面的事务,如果前面没有事务,则不开事务,通常在查询业务中
@Transactional(propagation = Propagation.REQUIRES_NEW) 不管前面业务是否有事务,都要独立创建新事务。
@Transactional(propagation = Propagation.NOT_SUPPORTED) 不支持事务
7)mysql关系型数据库,且存储引擎是MyISAM而非InnoDB,则事务会不起作用(很少见)MyISAM不支持事务
参考文章:https://blog.csdn.net/xuan_lu/article/details/107797505
5、MySQL一张表中有1千万条数据,现在查询比较慢,有什么优化思路?(必问)
或:请问MySQL优化的思路?
1)SQL语句优化,如:需要什么查询什么避免用* , 尽量比较时用于>= <= 尽可能用exits not exits,少用in not in like的百分号不要放左边
2)需要考虑对查询频繁的字段建立索引或联合(复合)索引。
但是要避免写SQL语句时索引失效的情况,如何得知SQL是否执行索引?使用explain查询执行计划
常见的可能导致索引失效的情况:
使用or,in like查询%放在左边
如在使用联合索引,遵守最左前缀原则
最左前缀原则是这样: (name,age,sex)
where name = jack ok
where name = jack and age>=10 ok
where age >10 and sex = “男” 不ok
3)如果说单表数据太多(过千万),可以采用水平分库分表(采用ShardingJdbc技术)
4)如果业务数据用于复杂的查询场景,把MySQL数据导入到Elasticsearch中,进行全文检索,从而效率更高。
