一次计算可以处理的最大数据长度
请求方法,请求url,http协议及版本
两者的区别特点
hashcode,equals
wait、notify
toString、
在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值
;{}替换成变量的值
使用#{}可以有效的防止 SQL 注入,提高系统安全性
底层是hashmap和双向链表,每一个entry都有一个前项entry和一个后项entry
除了跳跃表之外的,ziplist,skiplist
https://www.cnblogs.com/fanguangdexiaoyuer/p/10562069.html#_label0
可以设置不同aop的order来实现执行的顺序,order越小越是最先执行,更重要的是最先执行的最后结束。spring AOP就是面向切面编程,什么是切面,画一个图来理解下:
mvcc多版本控制,每个事务内只能读取比当前事务版本号低的数据。
全局无序,在同一个topic下,各个分区内部是有序的,使用offset来进行标识顺序。
如果对某些业务需要实现有序的话,我们可以设置这条消息的key,来保证所有这个key的消息都被分配到同一个分区中。
在kafka的分区器中,首先检查ProduceRecord中是否有key,如果有key的话,则使用散列算法计算对应的分区号,这样就可以实现所有相同key的消息都在同一个分区下,保证这个key的消息都是有序的。此时分区器分到的分区是所有分区
。
如果produceRecord中,没有key的话,那么分区器将自己使用使用轮询来分配,但是可分配的分区均在可用分区
中分配,而不是所有分区。
在Redis集群中,总共有16000多个插槽(slot),然后集群会将每一个key的有效部分(或者整个key)根据CRC16进行散列,对应到一个特定的插槽中,而集群中的每一台服务器,都只是负责其中一部分插槽。通过这种集群方式,Redis实现整体的内存分配。
面对上面的问题,我们可以采取如下策略
:
对这个key进行分组,比如传入进来的key-value为:<user:userId , value>,然后我们对这个key进行分组。比如说根据value的值,value在区间[0,100]时,将其分配给A组,此时的key变为:user:userid.A , 当value在区间[100,200]之内时,分配给B组,此时对key进行改造,成为了:user:userid.B。通过这种方式,可以将一个key-set结构存储量很大的情况,转换到不同的key中,散列到不同的slot内,相当于将这个key进行散列到了集群中的不同节点中。
阻塞IO为BIO,非阻塞IO为NIO
属于文本的操作工具,与grep,sed并称三大文本工具。
对比其他模型的问题,epoll的改进如下:
(1)支持一个进程打开大数目的socket描述符(FD)select 最不能忍受的是一个进程所打开的FD是有一定限制的,由FD_SETSIZE设置,默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核,不过资料也同时指出这样会带来网络效率的下降,二是可以选择多进程的解决方案(传统的 Apache方案),不过虽然linux上面创建进程的代价比较小,但仍旧是不可忽视的,加上进程间数据同步远比不上线程间同步的高效,所以也不是一种完美的方案。不过 epoll则没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
(2)IO效率不随FD数目增加而线性下降传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是"活跃"的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会
,在这点上,epoll实现了一个"伪"AIO,因为这时候推动力在os内核。在一些 benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll并不比select/poll有什么效率,相反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。
(3)使用mmap加速内核与用户空间的消息传递这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话,一定不会忘记手工 mmap这一步的。
①从上面的调用方式就可以看出epoll比select/poll的一个优势:select/poll每次调用都要传递所要监控的所有fd给select/poll系统调用(这意味着每次调用都要将fd列表从用户态拷贝到内核态,当fd数目很多时,这会造成低效)。而每次调用epoll_wait时(作用相当于调用select/poll),不需要再传递fd列表给内核,因为已经在epoll_ctl中将需要监控的fd告诉了内核(epoll_ctl不需要每次都拷贝所有的fd,只需要进行增量式操作)。所以,在调用epoll_create之后,内核已经在内核态开始准备数据结构存放要监控的fd了。每次epoll_ctl只是对这个数据结构进行简单的维护。
② 此外,内核使用了slab机制,为epoll提供了快速的数据结构:
在内核里,一切皆文件。所以,epoll向内核注册了一个文件系统,用于存储上述的被监控的fd。当你调用epoll_create时,就会在这个虚拟的epoll文件系统里创建一个file结点。当然这个file不是普通文件,它只服务于epoll。epoll在被内核初始化时(操作系统启动),同时会开辟出epoll自己的内核高速cache区,用于安置每一个我们想监控的fd,**这些fd会以红黑树的形式保存在内核cache里,以支持快速的查找、插入、删除。**这个内核高速cache区,就是建立连续的物理内存页,然后在之上建立slab层,简单的说,就是物理上分配好你想要的size的内存对象,每次使用时都是使用空闲的已分配好的对象。
③ epoll的第三个优势在于:当我们调用epoll_ctl往里塞入百万个fd时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的fd给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的fd外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。而且,通常情况下即使我们要监控百万计的fd,大多一次也只返回很少量的准备就绪fd而已,所以,epoll_wait仅需要从内核态copy少量的fd到用户态而已。那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把fd放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个fd的中断到了,就把它放到准备就绪list链表里。所以,当一个fd(例如socket)上有数据到了,内核在把设备(例如网卡)上的数据copy到内核中后就来把fd(socket)插入到准备就绪list链表里了。
就是有多少个备份
可以做搜索框中的前缀搜索,可以做复合查询,可以做存储系统
设计模式MVC
封装,多态,继承
安全的类
不是的,按照ack的数据,比如ack = 100,表示前100都收到了
可以
数据链路层
https://blog.csdn.net/wolenski/article/details/7951961
堆像一棵倒过来的树 堆就不同了,堆是一种经过排序的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。由于堆的这个特性,常用来实现优先队列,堆的存取是随意,这就如同我们在图书馆的书架上取书,虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
堆是非线性数据结构,相当于一维数组,有两个直接后继。
堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。
https://segmentfault.com/a/1190000012092552
当我们在浏览器中输入请求URL之后:
两者的区别
TCP:
DNS:是一种能进行主机名到IP地址转换的目录服务。这就是域名系统(domain name system , DNS)的主要任务。
定义:
DNS服务器通常是运行BIND软件的UNIX机器。DNS协议运行在UDP之上,使用53端口。
DNS的解析过程:
DNS的解析是按照分级的解析策略。按照上图,首先查找本地的DNS服务器,如果没有,则开始向上依次请求:根服务器---> 顶级域名服务器 ----> 权威域名服务器 -----> 本地DNS服务器。
因为经过的步骤比较多,所以在DNS的设计过程中,大量使用了DNS缓存。DNS缓存的原理:在一个请求链中,当某个DNS服务器接受一个DNS回答时,他能够将映射在本地存储器中。但并不是永久的。
详细过程:
一次结束之后,会断开
见百度一面面经
底层使用数组实现
hashmap,对entry进行了修改,加了一个before和next键值对,分别指向前一个和后一个entry,保证按照插入顺序进行遍历
https://zhuanlan.zhihu.com/p/79772089
主要是上下文切换:
开销分成两种,一种是直接开销、一种是间接开销。
(1)直接开销
就是在切换时,cpu必须做的事情,包括:
(2)间接开销
主要指的是虽然切换到一个新进程后,由于各种缓存并不热,速度运行会慢一些。如果进程始终都在一个CPU上调度还好一些,如果跨CPU的话,之前热起来的TLB、L1、L2、L3因为运行的进程已经变了,所以以局部性原理cache起来的代码、数据也都没有用了,导致新进程穿透到内存的IO会变多。 其实我们上面的实验并没有很好地测量到这种情况,所以实际的上下文切换开销可能比3.5us要大。
不包含
abc字符串的行见一点资讯二面面经
作业帮一面面经
多版本控制,可以用来保持数据一致性,并且使用在读已提交和可重复读两种隔离级别上。实现细节是,在每一行数据后面加两个隐藏列,然后对应于最后修改的事务的版本号,当前版本的事务号只能读取比当前版本号小的数据行。
有一种回收策略叫分代垃圾回收。
分代垃圾回收,顾名思义,是将jvm管理的堆,分为不同的部分进行gc策略以达到优化内存管理的效果。jvm将堆分为年轻代与老年代,年轻代中又分为eden区
与survivor区
。
jvm在给一个对象分配内存的时,会优先考虑将对象分配到eden区,如果是对象较大的情况下会直接将较大的对象放入老年代
,在eden区的对象,在minorGC后还存活会进入survivor区,在survivor区里存活时间较长的对象会进入老年代
里。
所以说一般说的垃圾回收有两种情况
,一种是发生在新生代的minorGC
,一种是发生在老年代的fullGC
。
而永久代
通常被称为方法区
,方法区主要用来存放运行时常量的
(1)MinorGC发生的时机
当jvm无法为新的对象
分配空间的时候就会发生Minor gc,所以分配对象的频率越高
,也就越容易发生Minor gc。
(2)Full GC发生的时机
class的信息、常量、静态变量
等数据,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,然后触发FullGC例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象
,此种情况就会触发JVM进行Full GC。主要发生在堆空间中的老年代内存不够的时候。
(1)jvm方面
(2)代码层面
不要创建过大的对象及数组。
@ControllerAdvice(annotations = Controller.class)
@ExceptionHandler({Exception.class})
setEx(过期时间)
https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/BIO-NIO-AIO.md
while(true)
循环中服务端会调用 accept()
方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接。Socket
和 ServerSocket
相对应的 SocketChannel
和 ServerSocketChannel
两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。了解一下阿里,京东,小米的技术架构,然后提前学习这些技术架构,为以后做准备。
共享内存、消息队列、管道、信号量、信号、套接字
https://juejin.im/post/6844903614998134797
http://mysql.taobao.org/monthly/2018/07/01/
在计算机领域,WAL(Write-ahead logging,预写式日志)是数据库系统提供原子性和持久化的一系列技术。
在使用WAL的系统中,所有的修改都先被写入到日志中,然后再被应用到系统状态中
。通常包含redo和undo两部分信息。
为什么需要使用WAL,然后包含redo和undo信息呢?举个例子,如果一个系统直接将变更应用到系统状态中,那么在机器掉电重启之后系统需要知道操作是成功了,还是只有部分成功或者是失败了(为了恢复状态)。如果使用了WAL,那么在重启之后系统可以通过比较日志和系统状态来决定是继续完成操作还是撤销操作
。
见作业帮一面面经
安全
不一定会发生
GC过程见农行一面面经
见作业帮一面面经
见拼多多二面面经