zoukankan      html  css  js  c++  java
  • 2020年Shopee面试问题整理

    ------------恢复内容开始------------
    个人的一二面记录:https://www.cnblogs.com/Jun10ng/p/12616409.html

    本文md文件在:https://github.com/Jun10ng/Gache/blob/master/Shopee面试问题整理.md
    给个start吧

    Shopee面试问题整理

    三握手四挥手 及其状态

    Go操作redis

    github 上面的rediGo

    什么是平衡二叉树

    编程:实现反转链表

    MySQL复合索引

    set的使用场景 有序set的使用场景

    有序且去重的场景

    1、 排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。

    2、用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

    反射 反射的弊端

    优点:运行期类型的判断,动态类加载,动态代理使用反射。

    缺点:性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。

    进程调度算法

    先来先服务 时间片轮转算法 短作业优先 最短剩余时间 高响应比 优先级

    进程间怎么通信

    管道 有名管道 套接字 消息队列 信号量

    线程间通信

    主要分为共享内存和消息传递

    volatile关键字 wait/notify机制

    事务隔离级别

    隔离级别 脏读(Dirty Read) 不可重复读 幻读(Phantom Read)

    未提交读(Read uncommitted) 可能 可能 可能

    已提交读(Read committed) 不可能 可能 可能

    可重复读(Repeatable read) 不可能 不可能 可能

    可串行化(Serializable ) 不可能 不可能 不可能

    MyISAM和InnoDB差别

    MyISAM不支持事务,InnoDB支持。MyISAM不支持行锁,只支持表锁,InnoDB支持行锁。

    InnoDB没有保存具体的行数,所以在统计行数的时候回扫描全表,MyISAM有保存。

    myisam的索引以表名+.MYI文件分别保存。innodb的索引和数据一起保存在表空间里。

    LINUX kill命令

    在Linux/unix下,中止一个Java进程有两种方式,一种是kill -9 pid,一种是kill -15 pill(默认)。

    SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略

    SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号(默认是15)。

    TCP四次挥手的TIME_WAIT

    在第三次挥手的时候,服务端发FIN给客户端,然后客户端再发ACK命令给客户端,然后进入TIME_WAIT状态,2MSL之后,进入CLOSED状态,从客户端的角度来说,第四次挥手是为了告诉服务端,我收到了你的FIN信号,一切正常,等待2MSL是为了确保服务端收到了ACK,如果因为网络波动导致服务端没收到ACK,那么服务端会重传FIN信号。从服务端的角度老说,第四次挥手能确保客户端收到FIN信号。

    TCP UDP

    TCP面向连接,UDP是无连接的,TCP能通过校验和,重传控制等,保证可靠传输,UDP不能保证可靠传输,但UDP实时性高且UDP对资源需要的少。

    TCP 如何保证数据传输的可靠性

    校验和 确认应答+序列号 超时重传 流量控制 拥塞控制

    TCP3次握手的过程,为什么要3次 ,SYN攻击

    大文件为什么越下载越快?

    滑动窗口,慢启动算法,越传越快。

    前面说过,还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”。一般来说ssthresh的值是65535,单位是字节,当cwnd达到这个值时后,算法如下:

    1)收到一个ACK时,cwnd = cwnd + 1/cwnd

    2)当每过一个RTT时,cwnd = cwnd + 1

    这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。很明显,是一个线性上升的算法。

    Innodb 自增主键

    上文讨论过InnoDB的索引实现,InnoDB使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)。

    如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时也不需要移动已有数据,因此效率很高,也不会增加很多开销在维护索引上。

    HTTP 无状态 无连接

    无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。为请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端,可以加KeepAlive弥补无连接的问题

    无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求,会给我们发送数据过来,但是,发送完,不会记录任何信息。 可以通过Cookie和Session来弥补这个问题。

    cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。

    Session的本质上也是cookie,但是不同点是存在服务器上的。这就导致,你如果使用cookie,你关闭浏览器之后,就丢掉Cookie了,但是如果关掉浏览器,重新打开之后,发现还有相应的信息,那就说明用的是Session。因为cookie是存在本地的,所以也会有相应的安全问题,攻击者可以去伪造他,填写相应的字段名,就能登录你的账户,还有如果cookie的有效期很长的话,也不安全。

    session 由服务器产生,对于客户端,只存储session id在cookie中。

    LRU算法是如何实现的?

    双向链表加 哈希表

    数组中出现次数最高的K个数

    map+优先队列

    先用map统计每个数的出现次数,然后维护 一个大小为K的优先队列(堆)。

    volatile 内存屏障

    CPU有可能会把相应代码的CPU指令进行一次重排序,这虽然能提高运行的效率,但是也可能会影响一些数据的可见性,而volatile通过 内存屏障 这个指令,来保证了相应代码块的执行顺序。内存屏障还会强制更新一次CPU缓存。加载最新的内容。

    快排的优化

    快排有三个步骤:

    1. 选择基准
    2. 分割操作
    3. 递归地对两个序列快速排列,直到序列为空或只有一个元素。

    所以可以针对这三个方面做优化

    选择基准:最理想的基准就是,每次划分都能分成登长的两个子序列。最坏的情况 就是基准是最大最小值。

    可以选的基准有:固定位置,随机位置,三数取中。

    三数取中是指 取 最左 最右 中间元素 三个数的中间值。

    其他优化方式

    1. 当排序序列分割到一定大小的时候,可以使用插入排序
    2. 如果有key相等的元素,可以聚在一起,下次排序的时候,就不用对相等的元素再排序了
    3. 优化递归操作
    4. 多线程

    Mysql 的 redo undo

    Undo日志记录某数据被修改前的值,可以用来在事务失败时进行回滚;Redo日志记录某数据块被修改后的值,可以用来恢复未写入data file的已成功事务更新的数据。

    死锁的四个条件 和预防

    互斥,不可剥夺,循环等待,请求和保持

    预防,检测,避免死锁,接触死锁

    银行家算法

    多路IO模型 NIO

    在多路复用IO模型中,会有一个线程(Java中的Selector)不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。

    五种网络IO模型

    阻塞IO 非阻塞IO 多路IO复用,信号驱动IO(不常用),异步IO,

    前四种都是同步IO

    像listen()、send()、recv()这些接口都是阻塞的,一问一答型的。这就给网络编程带来了一个问题,如果在调用send的时候,线程将被阻塞,在此期间,无法执行任何运算或相应任何的网络请求。于是有了多路IO模型,一个socket可以多次accept多次,比如Java中的selcetor 不断轮询多喝socket的状态,只有当socket真正有读写事件的时候,才会调用实际的IO读写操作,还有想Golang里的select+多个channel,这样只需要一个线程就可以管理多个socket,能减少大量资源占用。

    非阻塞IO模型

    在非阻塞IO模型中,用户进程不需要主动询问对方是否准备好数据与否,比如进程发出read操作,如果对方没有准备好,会返回一个error,这表示对方没有准备好,但是进程并不会阻塞在这一步,而是继续执行,等对方准备好数据后,再去调用它。

    异步IO

    异步IO是真正意义上的非阻塞IO,用户进程发起read操作后,立刻就可以开始做其他事,而另一方面,当他收到一个异步请求时,会立即返回一个值,所以不会对用户进程产生任何阻塞,等数据准备完后,再将数据拷贝到用户内存,当这一切都完成后,再给用户进程发送一个signal,告诉他read操作完成了。

    非阻塞IO和异步IO的区别

    虽然非阻塞IO在大多时间内不会被阻塞,但是它要求进程去主动监察对方数据是不是准备好了,一旦准备好了,会再次要求进程调用接收函数将数据拷贝过来。而异步IO完全不管这些,就像吧IO操作外包掉,等他人做完再发信号通知,这个期间内,进程不要检查也不用主动的去拷贝。

    Golang里的Sync包

    互斥锁:Mutex,读写锁:RWMutex. WaitGoup,Cond实现一个条件变量,Once 使对象只执行一次。

    Java线程的6种状态及切换

    初始:新建一个线程对象

    运行:调用了start后就是运行状态

    阻塞:线程被锁阻塞

    等待,进入该状态的线程需要等待其他线程做出一些动作(通知或者唤醒

    超时等待:

    终止:

    虚拟内存

    虚拟内存使得应用程序认为它拥有连续的可用内存,这样一来,就在逻辑层面上扩大了内存容量。但是实际上,只是把比较常用的内存片段取出来了而已,还有部分资源是放在磁盘存储器上的。需要的时候再进行数据交换。

    调度方式有,分页式,段式,段页式。比较流行方式是段页式,他结合了前两者的优点,以页为单位替换,以段为单位使用。

    常见的替换替换算法有4种,随机算法,先进先出算法,LRU算法,最优算法。 比较常使用的是LRU算法,他在redis里也有使用,当redis的内存满了的时候就是使用LRU算法替换掉旧内存。

    ------------恢复内容结束------------

  • 相关阅读:
    对MVC模型的自悟,详尽解释,为了更多非计算机人员可以理解
    openSUSE leap 42.3 实现有线 无线同时用
    Fedora27 源配置
    Ubuntu16.04添加HP Laserjet Pro M128fn打印机和驱动
    openSUSE leap 42.3 添加HP Laserjet Pro M128fn打印机和驱动
    OpenSUSE Leap 42.3下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    OpenSUSE Leap 42.3 安装java(Oracle jre)
    linux下支持托盘的邮件客户端Sylpheed
    Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    Firefox 浏览器添加Linux jre插件
  • 原文地址:https://www.cnblogs.com/Jun10ng/p/12616416.html
Copyright © 2011-2022 走看看