java面试(资料整理)

线程销毁(stop方法为什么剔除)

(1)设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止
(2)使用interrupt()方法中断线程
(3)使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和
     Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)
    stop()方法太过于暴力,会强行把执行一半的线程终止。这样会就不会保证线程的资源正确释放,通常是没有给与线程完成资源释放工作的机会,因此会导致程序工作在不确定的状态下

 

redis实现分布式锁,怎样查看锁状态 (采用的什么方式)

//获取锁的状态。可以加个判断 设定一个变量值 ,如果这个值是ok就是加锁成功,其他线程等待

    private static final String LOCK_SUCCESS = OK;
    private static final String SET_IF_NOT_EXIST = NX;
    private static final String SET_WITH_EXPIRE_TIME = PX;
  /**
  * 尝试获取分布式锁
  * @param jedis Redis客户端
  * @param lockKey 锁
  * @param requestId 请求标识
  * @param expireTime 超期时间
  * @return 是否获取成功
  */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);


        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

 

springcloud怎么做负载均衡的,分布式系统是怎样处理请求的

springcloud的 网关处理请求:
    采用Zuul网关进行分发

* PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
* ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
* POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
* ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。  

 

springCloud的5个组件

服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon
断路器——Netflix Hystrix
服务网关——Netflix Zuul
分布式配置——Spring Cloud Config
Eureka:Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
Ribbon:主要提供客户侧的软件负载均衡算法。Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。Ribbon内置可插拔、可定制的负载均衡组件。下面是用到的一些负载均衡策略:简单轮询负载均衡加权响应时间负载均衡区域感知轮询负载均衡随机负载均衡
Hystrix:断路器增加了稳定性和灵活性,以一个系统,提供稳定性,而系统从故障中恢复,并尽量减少此故障的对性能的影响。它可以帮助快速地拒绝对一个操作,即很可能失败,而不是等待操作超时(或者不返回)的请求,以保持系统的响应时间。如果断路器提高每次改变状态的时间的事件,该信息可以被用来监测由断路器保护系统的部件的健康状况,或以提醒管理员当断路器跳闸,以在打开状态。

 

redis的主从复制

(推荐  《redis的设计与实现》 1.数据结构<跳跃表,常用数据类型>

            2.持久化,过期策略

            3.主从复制,检测选举,集群

            4.发布订阅,事务,排序,日志)

 

 

 

1)采用异步复制;
2)一个主redis可以含有多个从redis;
3)每个从redis可以接收来自其他从redis服务器的连接;
4)主从复制对于主redis服务器来说是非阻塞的,这意味着当从服务器在进行主从复制同步过程中,主redis仍然可以处理外界的访问请求;
5)主从复制对于从redis服务器来说也是非阻塞的,这意味着,即使从redis在进行主从复制过程中也可以接受外界的查询请求,只不过这时候从redis返回的是以前老的数据,
   如果你不想这样,那么在启动redis时,可以在配置文件中进行设置,那么从redis在复制同步过程中来自外界的查询请求都会返回错误给客户端;(虽然说主从复制过程中
   对于从redis是非阻塞的,但是当从redis从主redis同步过来最新的数据后还需要将新数据加载到内存中,在加载到内存的过程中是阻塞的,在这段时间内的请求将会被阻,
   但是即使对于大数据集,加载到内存的时间也是比较多的);
6)主从复制提高了redis服务的扩展性,避免单个redis服务器的读写访问压力过大的问题,同时也可以给为数据备份及冗余提供一种解决方案;
7)为了编码主redis服务器写磁盘压力带来的开销,可以配置让主redis不在将数据持久化到磁盘,而是通过连接让一个配置的从redis服务器及时的将相关数据持久化到磁盘,
   不过这样会存在一个问题,就是主redis服务器一旦重启,因为主redis服务器数据为空,这时候通过主从同步可能导致从redis服务器上的数据也被清空;
 补充:
Redis数据类型
String 类型最适合简单的K-V储存,场景:短信验证码,配置信息
Hash 类型适合有id,唯一标识。场景:商品的详情,个人信息的详情
list 类型有序的,适合有序且相对固定的数据。 场景:省市县,字典表。按时间储存当作队列使用
set 类型可点理解为 ID-list 优点:可以对集合进行 交集,并集,差集的操作
zset 是set的增强版,有一个score的参数,可以根据score参数进行排序。场景:top10商品不根据时间进行排序

Redis(持久化)RDB
redis是一个内存数据库, 内存保存到磁盘,会在每个时间段,以快照的形式进行保存
RDB:以快照的形式进行保存
AOF:
    默认不开启,需要在配置文件中 修改appendonly no。改为yes 默认储存文件为 appendonly.aof
    如果appendonly.aof 文件损毁。可以使用bin目录下的,redis-check-aof进行修复
    修复命令:redis-check-aof -—fix appendonly.aof

触发机制
1.save的规则满足的情况下,会自动触发rdb规则
2.执行flushall的时候 会触发 rdb 规则
3.推出redis,也会产生rdb文件
会自动生成dump.rdb文件


优点:
适合大规模恢复数据
对数据完整性要求不高


缺点:
需要一定的时间间隔进程进行操作!如果redis意外dang机,最后一次修改的数据就没了
fork进程的时候,会占用一定内存
========================================================================================================

缓存雪崩
同一时间大量的key失效,这个时间有很多的请求。打在数据库上造成崩溃
解决方案
1.缓存过期时间 设置为分批次的,防止同时间key大面积失效
2.加锁排队
3.给每个缓存数据 增加相应的标记,记录缓存是否失效,就更新缓存数据

缓存穿透
请求的数据 redis缓存没有,数据库也没有。这样大批量的数据请求打在数据库上就造成数据库崩掉。
解决方案:
1.接口层增加校验,查询这个id在数据库的数量 id<=0 直接拦截
2.把缓存,数据库同时查不到的数据,直接赋值为null ,设置过期时间短一点
3.采用布隆过滤器


缓存击穿
redis缓存中没有但数据库中有的数据, 这时候来了大量请求 全部打在数据库上 造成击穿
解决方案:
1.设置热点数据永不过期
2.加锁

缓存预热
就是项目上线之后直接 将缓存数据加载到缓存系统。
解决方案:
1.数据量不大,启动的时候自动进行加载
2.定时刷新缓存

缓存热点
缓存降级:
目的:防止redis服务故障,导致数据的雪崩
    对于不重要的缓存,可以采用服务降级。常见的做法就是。用户请求发过来 redis没有查到,直接返回默认值。不查询数据库
=========================================================================================================
redis在缓存的内存不足时,怎么处理新写入且需要申请额外的空间的数据

noeviction:当内存不足以容纳新写入的数据,写入就会报错
allkeys-lru:当内存不足以容纳新写入的数据时,在建空间中,移除最少使用的这些键
allkeys-random:当内存不足以容纳新写的数据时,在键空间中,随机的移除某个key

设置过期时间的键空间选择性移除
volatile-lru:当内存不足以容纳新写入的数据时,在设置过期时间的键空间中,移除最近最少使用的那个key
volatile-random:当内存不足以容纳新写入的数据时,在设置过期时间的键空间中,随机移除一个key
volatile-ttl:当内存不足以容纳新写入的数据时,在设置过期时间的键空间中,有更早过期时间的key优先移除

 

线程池参数,以及拒绝策略
1.corePoolSize
2.maxPoolSize
3.keepAliveTime:空闲的线程多久时间后被销毁。默认情况下,改值在线程数大于corePoolSize时,对超出corePoolSize值得这些线程起作用。
4.TimeUnit:时间单位
5.workQueue
6.threadFactory
7.handler

队列
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
PriorityBlockingQueue

拒绝策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

ThreadLocal

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:
* 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
* 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。

线程死锁

什么是死锁?
两个或两个以上的线程,在竞争资源的时候。造成阻塞的现象就称为死锁。

什么情况下回 造成死锁?
1.

形成死锁的必要条件
1.互斥条件:线程对于所分配到的资源具有排他性,即一个资源只能被一个线程占用,直到该线程被释放
2.请求与保持条件:一个线程因请求被占用资源而发生阻塞时,对已获得资源保持不放。
3.不剥夺条件:线程已经获得的资源在未使用完之前不能被其他线程剥夺,只有自己使用完毕后才能释放资源。
4:循环等待条件:当发生死锁的时候,所等待的线程必定会形成一个环路,造成永久阻塞

如何避免死锁?

1.破坏互斥条件(不可取  因为我们用锁本来就是想让线程 互斥)
2.破坏请求与保持条件
    一次性申请所有的资源
3.破坏不剥夺条件
    占用部分线程的资源的线程进一步申请其他资源时,如果申请不到,可以主动释放他占有的资源
4.破坏循环等待条件
    考按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件

线程的三大特性
1.原子性
2.可见性
3.有序性

dubbo五个角色

 

 zookeeper选举问题

这篇主要分析leader的选择机制,zookeeper提供了三种方式:
* LeaderElection  
* AuthFastLeaderElection
* FastLeaderElection (最新默认)

目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
* 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking(选举状态)。
* 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
* 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
* 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
* 服务器5启动,后面的逻辑同服务器4成为小弟。

rabbitMQ五种模式

simple模式(简单的收发模式):点对点发送 及时消息
work模式:
publish订阅模式:
routing路由模式:
topic主题模式:

 

 

 

 

 

 

 

 数据库

innorDB 事物安全储存引擎

创建索引的注意的点:
1.哪些字段可以建索引,一般都where、order by 或者 group by 后面的字段。
2.对于单列索引来说,比较适合建在重读度低的列上。

使用顺序
group by -> having -> order by -> limit

索引:聚集索引、唯一索引、普通索引、联合索引、覆盖索引
ALTER TABLE user_innodb add INDEX comidx_name_phone(name,phone); -- 创建联合索引
alter table table_name add primary key(c
olum_name)。--创建聚集索引

创建索引实例:
首先创建一个表:create table students (id int primary key,name varchar(20),age Int);
创建单个索引的语法:create index 索引名 on 表名(字段名)
索引名一般是:表名_字段名
给id创建索引:create index students _id on students (id);
创建联合索引的语法:create index 索引名 on 表名(字段名1,字段名2)
给name和age创建联合索引:create index students _name_age on students (name,age)
建检索。 我们需要观察检索的sql的where条件,排列顺序满足最左原则,
聚簇索引和非聚簇索引

什么时候走索引,什么时候不走
1.首先查询的列是已经加了索引的

mysql的锁
乐观锁:采用了版本比较
悲观锁:读锁和写锁。行锁和间隙锁,表锁
    (如果where条件)
什么是死锁? 两个或两个以上的线程,在竞争资源的时候。造成阻塞的现象就称为死锁。 什么情况下回 造成死锁?
1. 形成死锁的必要条件 1.互斥条件:线程对于所分配到的资源具有排他性,即一个资源只能被一个线程占用,直到该线程被释放 2.请求与保持条件:一个线程因请求被占用资源而发生阻塞时,对已获得资源保持不放。 3.不剥夺条件:线程已经获得的资源在未使用完之前不能被其他线程剥夺,只有自己使用完毕后才能释放资源。 4:循环等待条件:当发生死锁的时候,所等待的线程必定会形成一个环路,造成永久阻塞 如何避免死锁? 1.破坏互斥条件(不可取 因为我们用锁本来就是想让线程 互斥) 2.破坏请求与保持条件 一次性申请所有的资源 3.破坏不剥夺条件 占用部分线程的资源的线程进一步申请其他资源时,如果申请不到,可以主动释放他占有的资源 4.破坏循环等待条件 考按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件

常见web攻击

SQL注入能使攻击者绕过认证机制,完全控制远程服务器上的数据库
例子:select id from users where username = '"+username +"' and password = '"  + password +”'
     select id from users where username = '' or 1=1--  and password = '123'

xss:跨站脚本攻击,前端页面插入一些恶意代码。钓鱼攻击

csrf:跨站点请求伪造
设置过期时间
一次token验证
场景合适直接上 cas 单点登录

 

整理的资料:

<a href="http!s://pa!n.baidu.co!m/s/1klAWDF!GQ0-FOJ-r6mqICLQ">删除!号</a>
<a target="m131">TiQU码</a>

 

posted @ 2021-03-15 17:09  Money131  阅读(424)  评论(0编辑  收藏  举报