面试集锦2

TCP 与 HTTP

http1.0 和 http1.1 有什么区别。

HTTP 1.0主要有以下几点变化:

请求和相应可以由于多行首部字段构成

响应对象前面添加了一个响应状态行

响应对象不局限于超文本

服务器与客户端之间的连接在每次请求之后都会关闭

实现了Expires等传输内容的缓存控制

内容编码Accept-Encoding、字符集Accept-Charset等协商内容的支持

这时候开始有了请求及返回首部的概念,开始传输不限于文本(其他二进制内容)

HTTP 1.1加入了很多重要的性能优化:持久连接、分块编码传输、字节范围请求、增强的缓存机制、传输编码及请求管道。

http://imweb.io/topic/554c5879718ba1240cc1dd8a

TCP 三次握手和四次挥手的流程,为什么断开连接要 4 次,如果握手只有两次,会出现什么。

第一次握手(SYN=1, seq=x):

客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。

发送完毕后,客户端进入SYN_SEND状态。

第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。

发送完毕后,服务器端进入SYN_RCVD状态。

第三次握手(ACK=1,ACKnum=y+1)

客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1

发送完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态,TCP 握手结束。

第一次挥手(FIN=1,seq=x)

假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。

发送完毕后,客户端进入 FIN_WAIT_1 状态。

第二次挥手(ACK=1,ACKnum=x+1)

服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。

发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

第三次挥手(FIN=1,seq=y)

服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。

发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

第四次挥手(ACK=1,ACKnum=y+1)

客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。

服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

两次后会重传直到超时。如果多了会有大量半链接阻塞队列。

https://segmentfault.com/a/1190000006885287

https://hit-alibaba.github.io/interview/basic/network/TCP.html

TIME_WAIT 和 CLOSE_WAIT 的区别。

TIME_WAIT状态就是用来重发可能丢失的ACK报文。

TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。

说说你知道的几种 HTTP 响应码,比如 200, 302, 404。

1xx:信息,请求收到,继续处理

2xx:成功,行为被成功地接受、理解和采纳

3xx:重定向,为了完成请求,必须进一步执行的动作

4xx:客户端错误,请求包含语法错误或者请求无法实现

5xx:服务器错误,服务器不能实现一种明显无效的请求

200 ok 一切正常

302 Moved Temporatily 文件临时移出

404 not found

https://my.oschina.net/gavinjin/blog/42856

当你用浏览器打开一个链接的时候,计算机做了哪些工作步骤。

Dns解析–>端口分析–>tcp请求–>服务器处理请求–>服务器响应–>浏览器解析—>链接关闭

TCP/IP 如何保证可靠性,说说 TCP 头的结构。

使用序号,对收到的TCP报文段进行排序以及检测重复的数据;使用校验和来检测报文段的错误;使用确认和计时器来检测和纠正丢包或延时。//TCP头部,总长度20字节

typedef struct _tcp_hdr

{

unsigned short src_port; //源端口号

unsigned short dst_port; //目的端口号

unsigned int seq_no; //序列号

unsigned int ack_no; //确认号

#if LITTLE_ENDIAN

unsigned char reserved_1:4; //保留6位中的4位首部长度

unsigned char thl:4; //tcp头部长度

unsigned char flag:6; //6位标志

unsigned char reseverd_2:2; //保留6位中的2位

#else

unsigned char thl:4; //tcp头部长度

unsigned char reserved_1:4; //保留6位中的4位首部长度

unsigned char reseverd_2:2; //保留6位中的2位

unsigned char flag:6; //6位标志

#endif

unsigned short wnd_size; //16位窗口大小

unsigned short chk_sum; //16位TCP检验和

unsigned short urgt_p; //16为紧急指针

}tcp_hdr;

https://zh.bywiki.com/zh-hans/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE

如何避免浏览器缓存。

无法被浏览器缓存的请求:

HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求

需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的

经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存,参考《HTTPS的七个误解》)

POST请求无法被缓存

HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存

http://www.alloyteam.com/2012/03/web-cache-2-browser-cache/

简述 Http 请求 get 和 post 的区别以及数据包格式。

面试集锦2_第1张图片
面试集锦2_第2张图片

http://www.w3school.com.cn/tags/html_ref_httpmethods.asp

http://www.360doc.com/content/12/0612/14/8093902_217673378.shtml

简述 HTTP 请求的报文格式。

参考上面

HTTPS 的加密方式是什么,讲讲整个加密解密流程。

加密方式是tls/ssl,底层是通过对称算法,非对称,hash算法实现

客户端发起HTTPS请求 –》2. 服务端的配置 –》

3. 传送证书 —》4. 客户端解析证书 5. 传送加密信息 6. 服务段解密信息 7. 传输加密后的信息 8. 客户端解密信息

http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html

架构设计与分布式

常见的缓存策略有哪些,你们项目中用到了什么缓存系统,如何设计的。

Cdn缓存,redis缓存,ehcache缓存等

Cdn 图片资源 js等, redis一主一从 echcache缓存数据

用 java 自己实现一个 LRU。

final int cacheSize = 100;

Map

分布式集群下如何做到唯一序列号。

Redis生成,mongodb的objectId,zk生成

http://www.cnblogs.com/haoxinyue/p/5208136.html

设计一个秒杀系统,30 分钟没付款就自动关闭交易。

分流 – 限流–异步–公平性(只能参加一次)–用户体验(第几位,多少分钟,一抢完)

容错处理

Redis 队列 mysql

30分钟关闭 可以借助redis的发布订阅机制 在失效时进行后续操作,其他mq也可以

http://www.infoq.com/cn/articles/yhd-11-11-queuing-system-design

如何使用 redis 和 zookeeper 实现分布式锁?有什么区别优缺点,分别适用什么场景。

首先分布式锁实现常见的有数据库锁(表记录),缓存锁,基于zk(临时有序节点可以实现的)的三种

Redis适用于对性能要求特别高的场景。redis可以每秒执行10w次,内网延迟不超过1ms

缺点是数据存放于内存,宕机后锁丢失。

锁无法释放?使用Zookeeper可以有效的解决锁无法释放的问题,因为在创建锁的时候,客户端会在ZK中创建一个临时节点,一旦客户端获取到锁之后突然挂掉(Session连接断开),那么这个临时节点就会自动删除掉。其他客户端就可以再次获得锁。

非阻塞锁?使用Zookeeper可以实现阻塞的锁,客户端可以通过在ZK中创建顺序节点,并且在节点上绑定监听器,一旦节点有变化,Zookeeper会通知客户端,客户端可以检查自己创建的节点是不是当前所有节点中序号最小的,如果是,那么自己就获取到锁,便可以执行业务逻辑了。

不可重入?使用Zookeeper也可以有效的解决不可重入的问题,客户端在创建节点的时候,把当前客户端的主机信息和线程信息直接写入到节点中,下次想要获取锁的时候和当前最小的节点中的数据比对一下就可以了。如果和自己的信息一样,那么自己直接获取到锁,如果不一样就再创建一个临时的顺序节点,参与排队。

单点问题?使用Zookeeper可以有效的解决单点问题,ZK是集群部署的,只要集群中有半数以上的机器存活,就可以对外提供服务。

http://www.hollischuang.com/archives/1716

如果有人恶意创建非法连接,怎么解决。

可以使用filter过滤处理

分布式事务的原理,优缺点,如何使用分布式事务。

Two Phase commit协议

优点是可以管理多机事务,拥有无线扩展性 确定是易用性难,承担延时风险

JTA,atomiks等

https://yq.aliyun.com/webinar/join/185?spm=5176.8067841.0.0.RL4GDa

什么是一致性 hash。

一致性hash是一种分布式hash实现算法。满足平衡性 单调性 分散性 和负载。

http://blog.csdn.net/cywosp/article/details/23397179/

什么是 restful,讲讲你理解的 restful。

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。

http://baike.baidu.com/link?url=fTSAdL-EyYvTp9z7mZsCOdS3kbs4VKKAnpBLg3WS_1Z4cmLMp3S-zrjcy5wakLTO5AIoPTopWVkG-IenloPKxq

如何设计建立和保持 100w 的长连接。

服务器内核调优(tcp,文件数),客户端调优,框架选择(netty)

如何防止缓存雪崩。

缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

解决思路:

1,采用加锁计数,或者使用合理的队列数量来避免缓存失效时对数据库造成太大的压力。这种办法虽然能缓解数据库的压力,但是同时又降低了系统的吞吐量。

2,分析用户行为,尽量让失效时间点均匀分布。避免缓存雪崩的出现。

3,如果是因为某台缓存服务器宕机,可以考虑做主备,比如:redis主备,但是双缓存涉及到更新事务的问题,update可能读到脏数据,需要好好解决。

http://www.cnblogs.com/jinjiangongzuoshi/archive/2016/03/03/5240280.html

解释什么是 MESI 协议(缓存一致性)。

MESI是四种缓存段状态的首字母缩写,任何多核系统中的缓存段都处于这四种状态之一。我将以相反的顺序逐个讲解,因为这个顺序更合理:

失效(Invalid)缓存段,要么已经不在缓存中,要么它的内容已经过时。为了达到缓存的目的,这种状态的段将会被忽略。一旦缓存段被标记为失效,那效果就等同于它从来没被加载到缓存中。

共享(Shared)缓存段,它是和主内存内容保持一致的一份拷贝,在这种状态下的缓存段只能被读取,不能被写入。多组缓存可以同时拥有针对同一内存地址的共享缓存段,这就是名称的由来。

独占(Exclusive)缓存段,和S状态一样,也是和主内存内容保持一致的一份拷贝。区别在于,如果一个处理器持有了某个E状态的缓存段,那其他处理器就不能同时持有它,所以叫“独占”。这意味着,如果其他处理器原本也持有同一缓存段,那么它会马上变成“失效”状态。

已修改(Modified)缓存段,属于脏段,它们已经被所属的处理器修改了。如果一个段处于已修改状态,那么它在其他处理器缓存中的拷贝马上会变成失效状态,这个规律和E状态一样。此外,已修改缓存段如果被丢弃或标记为失效,那么先要把它的内容回写到内存中——这和回写模式下常规的脏段处理方式一样。

说说你知道的几种 HASH 算法,简单的也可以。

哈希(Hash)算法,即散列函数。 它是一种单向密码体制,即它是一个从明文到密文的不可逆的映射,只有加密过程,没有解密过程。 同时,哈希函数可以将任意长度的输入经过变化以后得到固定长度的输出

MD4 MD5 SHA

http://blog.jobbole.com/106733/

什么是 paxos 算法。

Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的”La”,此人现在在微软研究院)于1990年提出的一种基于消息传递的一致性算法。

http://baike.baidu.com/item/Paxos%20%E7%AE%97%E6%B3%95

什么是 zab 协议。

ZAB 是 Zookeeper 原子广播协议的简称

整个ZAB协议主要包括消息广播和崩溃恢复两个过程,进一步可以分为三个阶段,分别是:

发现 Discovery

同步 Synchronization

广播 Broadcast

组成ZAB协议的每一个分布式进程,都会循环执行这三个阶段,将这样一个循环称为一个主进程周期。

https://zzzvvvxxxd.github.io/2016/08/09/ZAB/

一个在线文档系统,文档可以被编辑,如何防止多人同时对同一份文档进行编辑更新。

点击编辑的时候,利用redis进行加锁setNX完了之后 expire 一下

也可以用版本号进行控制

线上系统突然变得异常缓慢,你如何查找问题。

逐级排查(网络,磁盘,内存,cpu),数据库,日志,中间件等也可通过监控工具排查。

说说你平时用到的设计模式。

单例, 代理,模板,策略,命令

http://www.jianshu.com/p/bdf65e4afbb0

Dubbo 的原理,数据怎么流转的,怎么实现集群,负载均衡,服务注册和发现。重试转发,快速失败的策略是怎样的。

Dubbo[]是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

Cluster 实现集群

在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。

Random LoadBalance:随机,按权重比率设置随机概率。

RoundRobin LoadBalance:轮循,按公约后的权重比率设置轮循比率。

LeastActive LoadBalance:最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash LoadBalance:一致性Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

快速失败,只发起一次调用,失败立即报错。

https://my.oschina.net/u/1378920/blog/693374

一次 RPC 请求的流程是什么。

1)服务消费方(client)调用以本地调用方式调用服务;

2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;

3)client stub找到服务地址,并将消息发送到服务端;

4)server stub收到消息后进行解码;

5)server stub根据解码结果调用本地的服务;

6)本地服务执行并将结果返回给server stub;

7)server stub将返回结果打包成消息并发送至消费方;

8)client stub接收到消息,并进行解码;

9)服务消费方得到最终结果。

异步模式的用途和意义。

异步模式使用与服务器多核,并发严重的场景

可提高服务吞吐量大,不容易受到冲击,可以采用并发策略,提高响应时间

缓存数据过期后的更新如何设计。

失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

命中:应用程序从cache中取数据,取到后返回。

更新:先把数据存到数据库中,成功后,再让缓存失效。

编程中自己都怎么考虑一些设计原则的,比如开闭原则,以及在工作中的应用。

开闭原则(Open Close Principle)

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

里氏代换原则(Liskov Substitution Principle)

子类型必须能够替换掉它们的父类型。

依赖倒转原则(Dependence Inversion Principle)

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程

接口隔离原则(Interface Segregation Principle)

建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少

组合/聚合复用原则

说要尽量的使用合成和聚合,而不是继承关系达到复用的目的

迪米特法则(Law Of Demeter)

迪米特法则其根本思想,是强调了类之间的松耦合,类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成影响,也就是说,信息的隐藏促进了软件的复用。

单一职责原则(Single Responsibility Principle)

一个类只负责一项职责,应该仅有一个引起它变化的原因

http://www.banzg.com/archives/225.html

设计一个社交网站中的“私信”功能,要求高并发、可扩展等等。 画一下架构图。

MVC 模式,即常见的 MVC 框架。

SSM SSH SSI等

聊了下曾经参与设计的服务器架构。

应用服务器怎么监控性能,各种方式的区别。

如何设计一套高并发支付方案,架构如何设计。

如何实现负载均衡,有哪些算法可以实现。

Zookeeper 的用途,选举的原理是什么。

Mybatis 的底层实现原理。

请思考一个方案,设计一个可以控制缓存总体大小的自动适应的本地缓存。

请思考一个方案,实现分布式环境下的 countDownLatch。

后台系统怎么防止请求重复提交。

可以通过token值进行防止重复提交,存放到redis中,在表单初始化的时候隐藏在表单中,添加的时候在移除。判断这个状态即可防止重复提交。

如何看待缓存的使用(本地缓存,集中式缓存),简述本地缓存和集中式缓存和优缺点。本地缓存在并发使用时的注意事项。

描述一个服务从发布到被消费的详细过程。

讲讲你理解的服务治理。

如何做到接口的幂等性。

算法

10 亿个数字里里面找最小的 10 个。

有 1 亿个数字,其中有 2 个是重复的,快速找到它,时间和空间要最优。

2 亿个随机生成的无序整数,找出中间大小的值。

给一个不知道长度的(可能很大)输入字符串,设计一种方案,将重复的字符排重。

遍历二叉树。

有 3n+1 个数字,其中 3n 个中是重复的,只有 1 个是不重复的,怎么找出来。

写一个字符串反转函数。

常用的排序算法,快排,归并、冒泡。 快排的最优时间复杂度,最差复杂度。冒泡排序的优化方案。

二分查找的时间复杂度,优势。

一个已经构建好的 TreeSet,怎么完成倒排序。

什么是 B+树,B-树,列出实际的使用场景。

数据库知识

数据库隔离级别有哪些,各自的含义是什么,MYSQL 默认的隔离级别是是什么。

·未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

·提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)

·可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读

·串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

MYSQL默认是RepeatedRead级别

MYSQL 有哪些存储引擎,各自优缺点。

MyISAM: 拥有较高的插入,查询速度,但不支持事务

InnoDB :5.5版本后Mysql的默认数据库,事务型数据库的首选引擎,支持ACID事务,支持行级锁定

BDB: 源自Berkeley DB,事务型数据库的另一种选择,支持COMMIT和ROLLBACK等其他事务特性

Memory :所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在Mysql重新启动时丢失

Merge :将一定数量的MyISAM表联合而成一个整体,在超大规模数据存储时很有用

Archive :非常适合存储大量的独立的,作为历史记录的数据。因为它们不经常被读取。Archive拥有高效的插入速度,但其对查询的支持相对较差

Federated: 将不同的Mysql服务器联合起来,逻辑上组成一个完整的数据库。非常适合分布式应用

Cluster/NDB :高冗余的存储引擎,用多台数据机器联合提供服务以提高整体性能和安全性。适合数据量大,安全和性能要求高的应用

CSV: 逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个.CSV文件。这是一种普通文本文件,每个数据行占用一个文本行。CSV存储引擎不支持索引。

BlackHole :黑洞引擎,写入的任何数据都会消失,一般用于记录binlog做复制的中继

另外,Mysql的存储引擎接口定义良好。有兴趣的开发者通过阅读文档编写自己的存储引擎。

http://baike.baidu.com/item/%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E

高并发下,如何做到安全的修改同一行数据。

使用悲观锁 悲观锁本质是当前只有一个线程执行操作,结束了唤醒其他线程进行处理。

也可以缓存队列中锁定主键。

乐观锁和悲观锁是什么,INNODB 的行级锁有哪 2 种,解释其含义。

乐观锁是设定每次修改都不会冲突,只在提交的时候去检查,悲观锁设定每次修改都会冲突,持有排他锁。

行级锁分为共享锁和排他锁两种 共享锁又称读锁 排他锁又称写锁

http://www.jianshu.com/p/f40ec03fd0e8

SQL 优化的一般步骤是什么,怎么看执行计划,如何理解其中各个字段的含义。

查看慢日志(show [session|gobal] status ),定位慢查询,查看慢查询执行计划 根据执行计划确认优化方案

Explain sql

select_type:表示select类型。常见的取值有SIMPLE(简单表,即不使用连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(union中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个SELECT)等。

talbe:输出结果集的表。

type:表的连接类型。性能由高到底:system(表中仅有一行)、const(表中最多有一个匹配行)、eq_ref、ref、ref_null、index_merge、unique_subquery、index_subquery、range、idnex等

possible_keys:查询时,可能使用的索引

key:实际使用的索引

key_len:索引字段的长度

rows:扫描行的数量

Extra:执行情况的说明和描述

http://blog.csdn.net/hsd2012/article/details/51106285

数据库会死锁吗,举一个死锁的例子,mysql 怎么解决死锁。

产生死锁的原因主要是:

(1)系统资源不足。

(2) 进程运行推进的顺序不合适。

(3)资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

这里提供两个解决数据库死锁的方法:

1)重启数据库(谁用谁知道)

2)杀掉抢资源的进程:

先查哪些进程在抢资源:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

杀掉它们:Kill trx_mysql_thread_id;

MYsql 的索引原理,索引的类型有哪些,如何创建合理的索引,索引如何优化。

索引是通过复杂的算法,提高数据查询性能的手段。从磁盘io到内存io的转变

普通索引,主键,唯一,单列/多列索引建索引的几大原则

1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可

http://tech.meituan.com/mysql-index.html

http://www.cnblogs.com/cq-home/p/3482101.html

聚集索引和非聚集索引的区别。

“聚簇”就是索引和记录紧密在一起。

非聚簇索引 索引文件和数据文件分开存放,索引文件的叶子页只保存了主键值,要定位记录还要去查找相应的数据块。

数据库中 BTREE 和 B+tree 区别。

B+是btree的变种,本质都是btree,btree+与B-Tree相比,B+Tree有以下不同点:

每个节点的指针上限为2d而不是2d+1。

内节点不存储data,只存储key;叶子节点不存储指针。

http://lcbk.net/9602.html

Btree 怎么分裂的,什么时候分裂,为什么是平衡的。

Key 超过1024才分裂B树为甚会分裂? 因为随着数据的增多,一个结点的key满了,为了保持B树的特性,就会产生分裂,就向红黑树和AVL树为了保持树的性质需要进行旋转一样!

ACID 是什么。

A,atomic,原子性,要么都提交,要么都失败,不能一部分成功,一部分失败。

C,consistent,一致性,事物开始及结束后,数据的一致性约束没有被破坏

I,isolation,隔离性,并发事物间相互不影响,互不干扰。

D,durability,持久性,已经提交的事物对数据库所做的更新必须永久保存。即便发生崩溃,也不能被回滚或数据丢失。

Mysql 怎么优化 table scan 的。

避免在where子句中对字段进行is null判断

应尽量避免在where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

避免在where 子句中使用or 来连接条件

in 和not in 也要慎用

Like查询(非左开头)

使用NUM=@num参数这种

where 子句中对字段进行表达式操作num/2=XX

在where子句中对字段进行函数操作

如何写 sql 能够有效的使用到复合索引。

由于复合索引的组合索引,类似多个木板拼接在一起,如果中间断了就无法用了,所以要能用到复合索引,首先开头(第一列)要用上,比如index(a,b) 这种,我们可以select table tname where a=XX 用到第一列索引 如果想用第二列 可以 and b=XX 或者and b like‘TTT%’

mysql 中 in 和 exists 区别。

mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。

如果查询的两个表大小相当,那么用in和exists差别不大。

如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:

not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

1.EXISTS只返回TRUE或FALSE,不会返回UNKNOWN。

2.IN当遇到包含NULL的情况,那么就会返回UNKNOWN。

数据库自增主键可能的问题。

在分库分表时可能会生成重复主键 利用自增比例达到唯一 自增1 2,3 等

https://yq.aliyun.com/articles/38438

消息队列

用过哪些 MQ,和其他 mq 比较有什么优缺点,MQ 的连接是线程安全的吗,你们公司的MQ 服务架构怎样的。

根据实际情况说明

我们公司用activeMQ 因为业务比较简单 只有转码功能,而amq比较简单

如果是分布式的建议用kafka

http://blog.csdn.net/sunxinhere/article/details/7968886

MQ 系统的数据如何保证不丢失。

基本都是对数据进行持久化,多盘存储

rabbitmq 如何实现集群高可用。

集群是保证服务可靠性的一种方式,同时可以通过水平扩展以提升消息吞吐能力。RabbitMQ是用分布式程序设计语言erlang开发的,所以天生就支持集群。接下来,将介绍RabbitMQ分布式消息处理方式、集群模式、节点类型,并动手搭建一个高可用集群环境,最后通过java程序来验证集群的高可用性。

  1. 三种分布式消息处理方式

  RabbitMQ分布式的消息处理方式有以下三种:

  1、Clustering:不支持跨网段,各节点需运行同版本的Erlang和RabbitMQ, 应用于同网段局域网。

  2、Federation:允许单台服务器上的Exchange或Queue接收发布到另一台服务器上Exchange或Queue的消息, 应用于广域网,。

  3、Shovel:与Federation类似,但工作在更低层次。

RabbitMQ对网络延迟很敏感,在LAN环境建议使用clustering方式;在WAN环境中,则使用Federation或Shovel。我们平时说的RabbitMQ集群,说的就是clustering方式,它是RabbitMQ内嵌的一种消息处理方式,而Federation或Shovel则是以plugin形式存在。

https://my.oschina.net/jiaoyanli/blog/822011

https://www.ibm.com/developerworks/cn/opensource/os-cn-RabbitMQ/

Redis,Memcached

redis 的 list 结构相关的操作。

LPUSH LPUSHX RPUSH RPUSHX LPOP RPOP BLPOP BRPOP LLEN LRANGE

https://redis.readthedocs.io/en/2.4/list.html

Redis 的数据结构都有哪些。

字符串(strings):存储整数(比如计数器)和字符串(废话。。),有些公司也用来存储json/pb等序列化数据,并不推荐,浪费内存

哈希表(hashes):存储配置,对象(比如用户、商品),优点是可以存取部分key,对于经常变化的或者部分key要求atom操作的适合

列表(lists):可以用来存最新用户动态,时间轴,优点是有序,确定是元素可重复,不去重

集合(sets):无序,唯一,对于要求严格唯一性的可以使用

有序集合(sorted sets):集合的有序版,很好用,对于排名之类的复杂场景可以考虑https://redis.readthedocs.io/en/2.4/list.html

Redis 的使用要注意什么,讲讲持久化方式,内存设置,集群的应用和优劣势,淘汰策略等。

持久化方式:RDB时间点快照 AOF记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。

内存设置 maxmemory used_memory

虚拟内存: vm-enabled yes

3.0采用Cluster方式,

Redis集群相对单机在功能上存在一些限制, 需要开发人员提前了解,

在使用时做好规避。 限制如下:

1) key批量操作支持有限。 如mset、 mget, 目前只支持具有相同slot值的

ke

y执

行批量操作。 对于映射为不同slot值的key由于执行mget、 mget等操作可

能存在于多个节点上因此不被支持。

2) key事务操作支持有限。 同理只支持多key在同一节点上的事务操

作, 当多个key分布在不同的节点上时无法使用事务功能。

3) key作为数据分区的最小粒度, 因此不能将一个大的键值对象如

ha

sh、 list等映射到不同的节点。

4) 不支持多数据库空间。 单机下的Redis可以支持16个数据库, 集群模

式下只能使用一个数据库空间, 即db0。

5) 复制结构只支持一层, 从节点只能复制主节点, 不支持嵌套树状复

制结构。

Redis Cluster是Redis的分布式解决方案, 在3.0版本正式推出, 有效地解

决了Redis分布式方面的需求。 当遇到单机内存、 并发、 流量等瓶颈时, 可

以采用Cluster架构方案达到负载均衡的目的。 之前, Redis分布式方案一般

有两种:

·客户端分区方案, 优点是分区逻辑可控, 缺点是需要自己处理数据路

由、 高可用、 故障转移等问题。

·代理方案, 优点是简化客户端分布式逻辑和升级维护便利, 缺点是加

重架构部署复杂度和性能损耗。

现在官方为我们提供了专有的集群方案: Redis Cluster, 它非常优雅地

解决了Redis集群方面的问题, 因此理解应用好Redis Cluster将极大地解放我

们使用分布式Redis的工作量, 同时它也是学习分布式存储的绝佳案例。

LRU(近期最少使用算法)TTL(超时算法) 去除ttl最大的键值

http://wiki.jikexueyuan.com/project/redis/data-elimination-mechanism.html

http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage

http://www.redis.cn/topics/cluster-tutorial.html

redis2 和 redis3 的区别,redis3 内部通讯机制。

集群方式的区别,3采用Cluster,2采用客户端分区方案和代理方案

通信过程说明:

1) 集群中的每个节点都会单独开辟一个TCP通道, 用于节点之间彼此

通信, 通信端口号在基础端口上加10000。

2) 每个节点在固定周期内通过特定规则选择几个节点发送ping消息。

3) 接收到ping消息的节点用pong消息作为响应。

当前 redis 集群有哪些玩法,各自优缺点,场景。

当缓存使用 持久化使用

Memcache 的原理,哪些数据适合放在缓存中。

基于libevent的事件处理

内置内存存储方式SLab Allocation机制

并不单一的数据删除机制

基于客户端的分布式系统

变化频繁,具有不稳定性的数据,不需要实时入库, (比如用户在线

状态、在线人数..)

门户网站的新闻等,觉得页面静态化仍不能满足要求,可以放入

到memcache中.(配合jquey的ajax请求)

redis 和 memcached 的内存管理的区别。

Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。

Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。

在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。

http://lib.csdn.net/article/redis/55323

Redis 的并发竞争问题如何解决,了解 Redis 事务的 CAS 操作吗。

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法:

1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。

2.服务器角度,利用setnx实现锁。

MULTI,EXEC,DISCARD,WATCH 四个命令是 Redis 事务的四个基础命令。其中:

MULTI,告诉 Redis 服务器开启一个事务。注意,只是开启,而不是执行

EXEC,告诉 Redis 开始执行事务

DISCARD,告诉 Redis 取消事务

WATCH,监视某一个键值对,它的作用是在事务执行之前如果监视的键值被修改,事务会被取消。

可以利用watch实现cas乐观锁

http://wiki.jikexueyuan.com/project/redis/transaction-mechanism.html

http://www.jianshu.com/p/d777eb9f27df

Redis 的选举算法和流程是怎样的

Raft采用心跳机制触发Leader选举。系统启动后,全部节点初始化为Follower,term为0.节点如果收到了RequestVote或者AppendEntries,就会保持自己的Follower身份。如果一段时间内没收到AppendEntries消息直到选举超时,说明在该节点的超时时间内还没发现Leader,Follower就会转换成Candidate,自己开始竞选Leader。一旦转化为Candidate,该节点立即开始下面几件事情:

1、增加自己的term。

2、启动一个新的定时器。

3、给自己投一票。

4、向所有其他节点发送RequestVote,并等待其他节点的回复。

如果在这过程中收到了其他节点发送的AppendEntries,就说明已经有Leader产生,自己就转换成Follower,选举结束。

如果在计时器超时前,节点收到多数节点的同意投票,就转换成Leader。同时向所有其他节点发送AppendEntries,告知自己成为了Leader。

每个节点在一个term内只能投一票,采取先到先得的策略,Candidate前面说到已经投给了自己,Follower会投给第一个收到RequestVote的节点。每个Follower有一个计时器,在计时器超时时仍然没有接受到来自Leader的心跳RPC, 则自己转换为Candidate, 开始请求投票,就是上面的的竞选Leader步骤。

如果多个Candidate发起投票,每个Candidate都没拿到多数的投票(Split Vote),那么就会等到计时器超时后重新成为Candidate,重复前面竞选Leader步骤。

Raft协议的定时器采取随机超时时间,这是选举Leader的关键。每个节点定时器的超时时间随机设置,随机选取配置时间的1倍到2倍之间。由于随机配置,所以各个Follower同时转成Candidate的时间一般不一样,在同一个term内,先转为Candidate的节点会先发起投票,从而获得多数票。多个节点同时转换为Candidate的可能性很小。即使几个Candidate同时发起投票,在该term内有几个节点获得一样高的票数,只是这个term无法选出Leader。由于各个节点定时器的超时时间随机生成,那么最先进入下一个term的节点,将更有机会成为Leader。连续多次发生在一个term内节点获得一样高票数在理论上几率很小,实际上可以认为完全不可能发生。一般1-2个term类,Leader就会被选出来。

Sentinel的选举流程

Sentinel集群正常运行的时候每个节点epoch相同,当需要故障转移的时候会在集群中选出Leader执行故障转移操作。Sentinel采用了Raft协议实现了Sentinel间选举Leader的算法,不过也不完全跟论文描述的步骤一致。Sentinel集群运行过程中故障转移完成,所有Sentinel又会恢复平等。Leader仅仅是故障转移操作出现的角色。

选举流程

1、某个Sentinel认定master客观下线的节点后,该Sentinel会先看看自己有没有投过票,如果自己已经投过票给其他Sentinel了,在2倍故障转移的超时时间自己就不会成为Leader。相当于它是一个Follower。

2、如果该Sentinel还没投过票,那么它就成为Candidate。

3、和Raft协议描述的一样,成为Candidate,Sentinel需要完成几件事情

1)更新故障转移状态为start

2)当前epoch加1,相当于进入一个新term,在Sentinel中epoch就是Raft协议中的term。

3)更新自己的超时时间为当前时间随机加上一段时间,随机时间为1s内的随机毫秒数。

4)向其他节点发送is-master-down-by-addr命令请求投票。命令会带上自己的epoch。

5)给自己投一票,在Sentinel中,投票的方式是把自己master结构体里的leader和leader_epoch改成投给的Sentinel和它的epoch。

4、其他Sentinel会收到Candidate的is-master-down-by-addr命令。如果Sentinel当前epoch和Candidate传给他的epoch一样,说明他已经把自己master结构体里的leader和leader_epoch改成其他Candidate,相当于把票投给了其他Candidate。投过票给别的Sentinel后,在当前epoch内自己就只能成为Follower。

5、Candidate会不断的统计自己的票数,直到他发现认同他成为Leader的票数超过一半而且超过它配置的quorum(quorum可以参考《redis sentinel设计与实现》)。Sentinel比Raft协议增加了quorum,这样一个Sentinel能否当选Leader还取决于它配置的quorum。

6、如果在一个选举时间内,Candidate没有获得超过一半且超过它配置的quorum的票数,自己的这次选举就失败了。

7、如果在一个epoch内,没有一个Candidate获得更多的票数。那么等待超过2倍故障转移的超时时间后,Candidate增加epoch重新投票。

8、如果某个Candidate获得超过一半且超过它配置的quorum的票数,那么它就成为了Leader。

9、与Raft协议不同,Leader并不会把自己成为Leader的消息发给其他Sentinel。其他Sentinel等待Leader从slave选出master后,检测到新的master正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程。

http://weizijun.cn/2015/04/30/Raft%E5%8D%8F%E8%AE%AE%E5%AE%9E%E6%88%98%E4%B9%8BRedis%20Sentinel%E7%9A%84%E9%80%89%E4%B8%BELeader%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/

redis 的持久化的机制,aof 和 rdb 的区别。

RDB 定时快照方式(snapshot): 定时备份,可能会丢失数据

AOF 基于语句追加方式 只追加写操作

AOF 持久化和 RDB 持久化的最主要区别在于,前者记录了数据的变更,而后者是保存了数据本身

redis 的集群怎么同步的数据的。

redis replication redis-migrate-tool等方式

搜索

elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段。elasticsearch 的倒排索引是什么。

ElasticSearch(简称ES)是一个分布式、Restful的搜索及分析服务器,设计用于分布式计算;能够达到实时搜索,稳定,可靠,快速。和Apache Solr一样,它也是基于Lucence的索引服务器,而ElasticSearch对比Solr的优点在于:

轻量级:安装启动方便,下载文件之后一条命令就可以启动。

Schemafree:可以向服务器提交任意结构的JSON对象,Solr中使用schema.xml指定了索引结构。

多索引文件支持:使用不同的index参数就能创建另一个索引文件,Solr中需要另行配置。

分布式:SolrCloud的配置比较复杂。

倒排索引是实现“单词-文档矩阵”的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

elasticsearch 索引数据多了怎么办,如何调优,部署。

使用bulk API

初次索引的时候,把 replica 设置为 0

增大 threadpool.index.queue_size

增大 indices.memory.index_buffer_size

增大 index.translog.flush_threshold_ops

增大 index.translog.sync_interval

增大 index.engine.robin.refresh_interval

http://www.jianshu.com/p/5eeeeb4375d4

lucence 内部结构是什么

索引(Index):

在Lucene中一个索引是放在一个文件夹中的。

如上图,同一文件夹中的所有的文件构成一个Lucene索引。

段(Segment):

一个索引可以包含多个段,段与段之间是独立的,添加新文档可以生成新的段,不同的段可以合并。

如上图,具有相同前缀文件的属同一个段,图中共三个段 “_0” 和 “_1”和“_2”。

segments.gen和segments_X是段的元数据文件,也即它们保存了段的属性信息。

文档(Document):

文档是我们建索引的基本单位,不同的文档是保存在不同的段中的,一个段可以包含多篇文档。

新添加的文档是单独保存在一个新生成的段中,随着段的合并,不同的文档合并到同一个段中。

域(Field):

一篇文档包含不同类型的信息,可以分开索引,比如标题,时间,正文,作者等,都可以保存在不同的域里。

不同域的索引方式可以不同,在真正解析域的存储的时候,我们会详细解读。

词(Term):

词是索引的最小单位,是经过词法分析和语言处理后的字符串。

你可能感兴趣的:(面试集锦2)