小滴课堂后端面试题(19)~持续更新中

一、引入队列有啥优缺点,对比其他消息中间产品,选择这款的原因是啥

回答

(一)优点:解耦系统、异步化、削峰
(二)缺点 : 系统可用性降低、复杂度增高、维护成本增高
(三)主流消息队列 Apache ActiveMQ Kafka RabbitMQ RocketMQ
(四)ActiveMQ http://activemq.apache.org/
Apache 出品,历史悠久,支持多种语言的客户端和协议,支持多种语言 Java, .NET, C++ 等,基于JMS Provider 的实现
缺点:吞吐量不高,多队列的时候性能下降,存在消息丢失的情况,比较少大规模使用
(四)Kafka http://kafka.apache.org/
是由 Apache 软件基金会开发的一个开源流处理平台,由 Scala Java 编写。 Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理大规模的网站中的所有动作流数据( 网页浏览, 搜索和其他用户的行动) ,副本集机制,实现数据冗余,保障数据尽量不丢失;支持多个生产
者和消费者
缺点:不支持批量和广播消息,运维难度大,文档比较少 , 需要掌握 Scala
(五)RabbitMQ http://www.rabbitmq.com/
是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种客户端,如: Python 、 Ruby、 .NET Java JMS C 、用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不错
缺点:使用 Erlang 开发,阅读和修改源码难度大
(六)RocketMQ http://rocketmq.apache.org/
1、阿里开源的一款的消息中间件 , Java 开发,具有高吞吐量、高可用性、适合大规模分布式系 统应用的特点, 性能强劲 ( 零拷贝技术 ) ,支持海量堆积 , 支持指定次数和时间间隔的失败消息重发, 支持 consumer tag 过滤、延迟消息等,在阿里内部进行大规模使用,适合在电商,互联网金融等领域使用
2、缺点:成熟的资料相对不多,社区处于新生状态但是热度高

二、用过线程池不? 有什么好处, java里有哪些是常用的线程池

回答

好处:重用存在的线程,减少对象创建销毁的开销,有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞,且可以定时定期执行、单线程、并发数控制,配置任务过多任务后的拒绝策略等功能 

类别
newFixedThreadPool 
    一个定长线程池,可控制线程最大并发数 

newCachedThreadPool 
    一个可缓存线程池 

newSingleThreadExecutor 
    一个单线程化的线程池,用唯一的工作线程来执行任务 

newScheduledThreadPool 
    一个定长线程池,支持定时/周期性任务执行

三、针对线上的数据库,你会做哪些监控,业务性能 + 数据安全角度分析

回答

大厂一般都有数据库监控后台,里面指标很多,但是开发人员也必须知道 

业务性能
    1、应用上线前会审查业务新增的sql,和分析sql执行计划 比如是否存在select*,索引建立是否合理 
    2、开启慢查询日志,定期分析慢查询日志 
    3、监控CPU/内存利用率,读写、网关IO、流量带宽 随着时间的变化统计图 
    4、吞吐量QPS/TPS,一天内读写随着时间的变化统计图 

数据安全
    1、短期增量备份,比如一周一次。 定期全量备份,比如一月一次 
    2、检查是否有非授权用户,是否存在弱口令,网络防火墙检查 
    3、导出数据是否进行脱敏,防止数据泄露或者黑产利用 
    4、数据库 全量操作日志审计,防止数据泄露 
    5、数据库账号密码 业务独立,权限独立控制,防止多库共用同个账号密码 
    6、高可用主从架构,多机房部署

四、知道AQS吗?能否介绍下,它的核心思想是什么

回答

AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。 
它是一个Java提高的底层同步工具类,比如CountDownLatch、ReentrantLock,Semaphore, ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于AQS的 

只要搞懂了AQS,那么J.U.C中绝大部分的api都能轻松掌握 

简单来说:是用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态对象 
一个是state(用于计数器,类似gc的回收计数器) 
一个是线程标记(当前线程是谁加锁的), 
一个是阻塞队列(用于存放其他未拿到锁的线程) 

例子:线程A调用了lock()方法,通过CAS将state赋值为1,然后将该锁标记为线程A加锁。如果线程A还未释放锁时,线程B来请求,会查询锁标记的状态,因为当前的锁标记为线程A,线程B未能匹配上,所以线程B会加入阻塞队列,直到线程A触发了unlock() 方法,这时线程B才有机会去拿到锁,但是不一定肯定拿到
acquire(int arg) 源码讲解,好比加锁lock操作 
tryAcquire()尝试直接去获取资源,如果成功则直接返回,AQS里面未实现但没有定义成abstract,因为独占模式下只用实现tryAcquire-tryRelease,而共享模式下只用实现tryAcquireShared-tryReleaseShared,类似设计模式里面的适配器模式 

addWaiter() 根据不同模式将线程加入等待队列的尾部,有Node.EXCLUSIVE互斥模式、 Node.SHARED共享模式;如果队列不为空,则以通过compareAndSetTail方法以CAS将当前线程节点加入 到等待队列的末尾。否则通过enq(node)方法初始化一个等待队列 

acquireQueued()使线程在等待队列中获取资源,一直获取到资源后才返回,如果在等待过程中被中断,则返回true,否则返回false 

release(int arg)源码讲解好比解锁unlock 
独占模式下线程释放指定量的资源,里面是根据tryRelease()的返回值来判断该线程是否已经完成释放掉资源了;在自义定同步器在实现时,如果已经彻底释放资源(state=0),要返回true,否则返回falseunparkSuccessor方法用于唤醒等待队列中下一个线程

五、知道ReentrantReadWriteLock吗?和ReentrantLock有啥不同?

回答

ReentrantReadWriteLock 
    1、读写锁接口ReadWriteLock接口的一个具体实现,实现了读写锁的分离, 
    2、支持公平和非公平,底层也是基于AQS实现 
    3、允许从写锁降级为读锁 
         流程:先获取写锁,然后获取读锁,最后释放写锁;但不能从读锁升级到写锁 
   
    4、重入:读锁后还可以获取读锁;获取了写锁之后既可以再次获取写锁又可以获取读锁 
    核心:读锁是共享的,写锁是独占的。 读和读之间不会互斥,读和写、写和读、写和写之间才会互斥, 主要是提升了读写的性能 


ReentrantLock是独占锁且可重入的,相比synchronized而言功能更加丰富也更适合复杂的并发场景,但是也有弊端,假如有两个线程A/B访问数据,加锁是为了防止线程A在写数据,线程B在读数据造成的数据不一致; 但线程A在读数据,线程C也在读数据,读数据是不会改变数据没有必要加锁,但是还是加锁了,降低了程序的性能,所以就有了ReadWriteLock读写锁接口


场景:读多写少,比如设计一个缓存组件 或 提高Collection的并发性 
class CachedData { 
 *   Object data; 
 *   volatile boolean cacheValid; 
 *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
 *
 *   void processCachedData() { 
 *     rwl.readLock().lock();
 *     if (!cacheValid) { 
 *       // Must release read lock before acquiring write lock 
 *       rwl.readLock().unlock(); 
 *       rwl.writeLock().lock(); 
 *       try { 
 *         // Recheck state because another thread might have 
 *        // acquired write lock and changed state before we did. 
 *        if (!cacheValid) { 
 *          data = ... 
 *          cacheValid = true; 
 *        } 
 *        // Downgrade by acquiring read lock before releasing write lock 
 *        rwl.readLock().lock(); 
 *      } finally { 
 *        rwl.writeLock().unlock(); // Unlock write, still hold read 
 *      } 
 *   } 
 *
 *   try { 
 *     use(data); 
 *   } finally { 
 *     rwl.readLock().unlock(); 
 *   } 
 *  } 
 * }} 

  class RWDictionary { 
 *   private final Map<String, Data> m = new TreeMap<String, Data>(); 
 *   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
 *   private final Lock r = rwl.readLock(); 
 *   private final Lock w = rwl.writeLock(); 
 *
 *   public Data get(String key) { 
 *     r.lock(); 
 *     try { return m.get(key); } 
 *     finally { r.unlock(); } 
 *   } 
 *   public String[] allKeys() { 
 *     r.lock(); 
 *     try { return m.keySet().toArray(); } 
 *     finally { r.unlock(); } 
 *   } 
 *   public Data put(String key, Data value) { 
 *     w.lock(); 
 *     try { return m.put(key, value); } 
 *     finally { w.unlock(); } 
 *   } 
 *   public void clear() { 
 *     w.lock(); 
 *     try { m.clear(); } 
 *     finally { w.unlock(); } 
 *  } 
 * }}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值