疏漏总结(五)

  1. tcp如何保证可靠性传输?
  • 校验和

在发送数据之前计算校验和,然后发送数据之后再次计算校验和,然后对比两次是否是相同的。

  • 序列号和确认应答

TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。

  • 超时重传

发送方没有介绍到响应的ACK报文原因可能有两点:

数据在传输过程中由于网络原因等直接全体丢包,接收方根本没有接收到。
接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。

发送方在发送完数据后等待一个时间,时间到达没有接收到ACK报文,那么对刚才发送的数据进行重新发送。如果是刚才第一个原因,接收方收到二次重发的数据后,便进行ACK应答。如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。

由于TCP传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。

在Linux中(BSD Unix和Windows下也是这样)超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

  • 连接管理

三次握手和四次挥手的过程。

  • 流量控制

接收端在接收到数据后,对其进行处理。如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,超时重传呀什么的。而TCP根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。

  • 拥塞控制

TCP引入了慢启动的机制,在开始发送数据时,先发送少量的数据探路。探清当前的网络状态如何,再决定多大的速度进行传输。这时候就引入一个叫做拥塞窗口的概念。发送刚开始定义拥塞窗口为 1,每次收到ACK应答,拥塞窗口加 1。在发送数据之前,首先将拥塞窗口与接收端反馈的窗口大小比对,取较小的值作为实际发送的窗口。

  1. bio nio aio简单介绍一下

io,本质上就是利用os进行一个read and write的操作,但是bio nio aio的主要区别就是在于同步异步,阻塞与非阻塞的区别上。

bio,同步阻塞,也就是当发起io请求,只有在请求到达缓冲区后,才能继续下一个请求,很废cpu,但是不容易出错。

nio,同步非阻塞,也就是发起io请求后,用户线程不原地等待IO缓冲区,可以先做一些其他操作,但是要定时轮询检查IO缓冲区数据是否就绪。这是一种多路复用的思想,IO多路复用模型中,将检查IO数据是否就绪的任务,交给系统级别的select或epoll模型,由系统进行监控,减轻用户线程负担。

主要有buffer、channel、selector三种技术的整合,通过零拷贝的buffer取得数据,每一个客户端通过channel在selector(多路复用器)上进行注册。服务端不断轮询channel来获取客户端的信息。channel上有connect,accept(阻塞)、read(可读)、write(可写)四种状态标识。根据标识来进行后续操作。所以一个服务端可接收无限多的channel。不需要新开一个线程。大大提升了性能。

aio,异步非阻塞,完全释放线程,linux上底层还是主要用epoll实现。
3. redis支持的几种数据类型中zset底层是怎么实现的?

skipList和zipList。有序集合保存的元素数量小于128个且保存的所有元素的长度小于64字节的时候用ziplist,其他的时候用跳表。

/*
 * 跳跃表
 */
typedef struct zskiplist {

    // 表头节点和表尾节点
    struct zskiplistNode *header, *tail;

    // 表中节点的数量
    unsigned long length;

    // 表中层数最大的节点的层数
    int level;

} zskiplist;
/*
 * 跳跃表节点
 */
typedef struct zskiplistNode {

    // 成员对象
    robj *obj;

    // 分值
    double score;

    // 后退指针
    struct zskiplistNode *backward;

    // 层
    struct zskiplistLevel {

        // 前进指针
        struct zskiplistNode *forward;

        // 跨度
        unsigned int span;

    } level[];

} zskiplistNode;
  1. hashmap分配key的运算是怎么样的,说说put操作

根据key进行哈希运算,之后进行一个&运算,选择出来分在哪个bucket里,然后头插(1.7头插,1.8尾插)进链表,如果出现哈希冲突,也就是计算后bucket相同,就会替换old value,比较的方法也是从链表头开始遍历,如果长度此时超过8,就会变成红黑树。

  1. 为什么hashmap的容量都是2的n次方

计算分到哪个bucket本质上用的是一种取余运算,但是取余效率不如位运算,而且,更大的程度是为了避免哈希冲突和提升效率,如果你用取余运算,就不需要2次方,如果你用位运算,就必须得2次方。

  1. synchronized和lock的区别
类别synchronizedLock
存在层次关键字接口
锁的释放以获取锁的线程执行完同步代码,释放锁,并且线程执行出现异常,也会释放锁在finally中必须释放锁,不然容易造成线程死锁
锁的获取假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待lock():获取锁,如果锁被暂用则一直等待
锁状态无法判断可以判断
锁类型可重入 不可中断 非公平可重入 可判断 可公平
性能少量同步大量同步
  1. redis为什么用跳表不用红黑树

①复杂度都一样,跳表实现起来更简单
②跳表每次插入数据,影响的只是局部,而红黑树有可能会导致rebalance
③跳表节省内存,但是费cpu资源,作为内存数据库,内存很重要。

  1. Mysql InnoDB引擎中对行锁的知识点遗漏

在mysql的行锁中,并不是真的锁住记录,而是锁索引,索引分为主键和非主键索引,如果一条sql操作的主键索引,那么就会触发主键索引的行锁,如果操作的是非主键索引,就会先触发非主键索引的行锁,再触发主键索引的行锁。如果操作的是不是索引的记录,就会通过聚簇索引来加锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值