后端技术阶段性学习总结

目录

写在前面:只是为了做笔记!!!

会持续不断地学习、更新,有喜欢的朋友一键三连啦~

一,网络协议

      Linux

    Nginx

          限流从类型上分有两种:限制速率,一种是限制并发,采用漏桶算法,依次以一定速率的流出

二,mysql

   1,mysql架构

2,InnoDB介绍

 2.1 整体架构图

内存池

重做日志

事务

MVCC原理:用锁(并发控制)+undolog (多版本)

当前读与快照读

死锁

Innodb关键特性

Innodb索引:

Mysql主从同步

Mysql一些问题

三,redis

   1,redis的五种常用类型及数据结构(string,list,hash,set,zset)

2,缓存击穿,穿透,雪崩和一致性问题

3,缓存过期策略

4,缓存主从+哨兵

    4.1,主从

       4.2,哨兵

   4.3,分布式系统数据一致性

四,PHP&Go

五,MQ

六,数据结构&算法


写在前面:只是为了做笔记!!!

会持续不断地学习、更新,有喜欢的朋友一键三连啦~

一,网络协议

      Linux

         select poll epoll

          select:有三种writefd,readfd,exceptfd(可读,可写,可接收),有最大长度限制,linux为1024,几乎所有平台都支持

          poll:用一个poll指针来指向就读的fd,但是是需要去轮询就绪的fd

          epoll:e是最大的改动(even事件回调),将用户关系的fd存放到一个事件表,先创建一个fd,注册进事件表,等待callback.在两种不同的模式下LT(回调通知不一定立执行),ET(高速模式)立即执行

    Nginx

          限流从类型上分有两种:限制速率,一种是限制并发,采用漏桶算法,依次以一定速率的流出

           速率:ngx_http_limit_req_module

          并发:ngx_http_limit_conn_module 

          白名单:ngx_http_geo_module 和 ngx_http_map_module      

          下载速度:ngx_http_limit_req_module 

     

1、limit_conn_zone

2、limit_req_zone

3、ngx_http_upstream_module:参数用max_conns限制最大并发数

//limit_conn_zone
http{

 limit_conn_zone $binary_remote_addr zone=one:10m;

 server

 {

   ......

  limit_conn one 10;

  ......

 }

} 

     tcp工作在传输层,传输包数据

      TCP三手握手:

         1,客户端发送一个初始序列号和syn=1请求标志

         2,服务端收到后返回一个syn请求标志,同时发送一个确认标志ack,自己的seq,客户端的ack+1

          3,客户端收到ack后,发送一个ack,自己的seq对方的ack

   三次是为了确保双方都知道自己接收发送正常

     四手挥手:

         1,客户端发出一个fin结束标志,自己的序列号seq=u,进入FIN-WAIT-1的状态

          2,服务端发送ack=1,对方的ack,自己的seq 进入close-wait状态

           3,客户端进入FIN-WAIT-2状态,服务端请求断开,发送seq ack,对方面的ack=对方的序列号+1,进入time-wait状态

           4,客户端收到后,断开请求,发送ack seq 对方的ack=邓方的序列号+1

当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,是否结束还需要等待上层应用决定,所以ack和fin分开过需要四次

    TCP拆包/粘包

           定义: 粘包就是一个较大的包与一个较小的包顺序传输时,较大的包有部分数据与较小的包粘在了一起,即发生了拆包与粘包

          原因:由于没有明确的包的界限,应用写入的数据大于套字节缓冲区,这会发生拆包,反之,粘包

         解决办法:

              1,明确边界,如特殊字符

              2,固定长度,不足用0等补足

              3,添加包首,包括包长度等信息

    

    IP工作在网络层

二,mysql

   1,mysql架构

        

   一条sql如果执行的

       先从连接器进行权限,用户校验,如果有缓存则直接返回结果,如果没再到第二层的解析器进行词法、语法检查,然后交给优化器进行索引优化,索引选择,再到执行器调用

engine接口,再返回 

2,InnoDB介绍

 2.1 整体架构图

å¾ç

内存池

å¾ç

   缓冲池( innodb_buffer_pool)

   参数:innodb_buffer_pool_size 调整缓存大小,通过lru(最近最小使用策略),利用checkpoint(擦除)机制将数据刷新到磁盘(PS:innodb是dml语句是先在缓冲区里操作)

重做日志

redo log(已修改记录日志) 保证事务的持久性,采用Write ahead Log方式,在事务提交时,先写重做日志,再修改页

redo log 在结构上分为两个部分:一个redo_log_buffer  一个redo_log_file

 redo log通常是物理日志,记录的是数据页的物理修改,用来恢复数据页最后一次提交的位置
   

//参数:
innodb_log_buffer_size  ##buffer大小

innodb_flush_log_at_trx_commit  ##多少次提交进行一次log file写入,默认为1

innodb_flush_log_at_timeout ##从缓冲写入的时间频率

undo log (回滚日志)是一个逻辑日志,用来回滚到行记录到某个版本

事务

   特性:ACID

      原子性(Atomicity):undo log

      隔离性(Isolation):锁

      持久性(Durability):redo log

     一致性(Consistency):redo log

  事务的实现就是通过redo log与锁机制

   事务的隔离级别

事务隔离级别描述实现原理脏读不可重复读幻读
READ UNCOMMITTED一个事务会读到另一个未提交事务修改过的数据。
READ COMMITTED一个事务只能读到另一个已经提交的事务修改过的数据。乐观锁+MVCC
REPEATABLE READ一个事务只能读到另一个已经提交的事务修改过的数据,而且该事务第一次读过某条记录后,即使其他事务修改了该记录的值并且提交,该事务之后再读该条记录时,读到的仍是第一次读到的值。乐观锁+MVCC是。解决方式:快照读:MVCC;2、当前读:next-key锁解决
SERIALIZABLE事务串行化执行悲观锁

Purge 最终实现delete update的操作,由于innodb支持mvcc,所以记录不能在事务提交时立即处理,因为还有其它事务在引用这行数据undo log (未修改记录日志) 保证事务的原子性,可回滚操作,和MVCC的实现

MVCC原理:用锁(并发控制)+undolog (多版本)

    1,表中每行的隐藏列:记录了一个事务的ID,一个指向上一个版本undo log的指针

     2,undo log的版本链

     3,read view(快照):在RR级别下,开启事务后,select时,会创建一个快照,把其它活跃的事务记录下来,RC就是每个select都会生成快照

     4,可见性判断:当前事务ID:trx_id_current,最早的事务ID up_limit_id,最晚的事务ID:low_limit_id

            口诀:当前事务ID小于最早的,可见;大于最晚的,不可见,在两者之间,如果这个事务ID存在于活跃中的不可见,不在可见,需要查找undo log上一个版本

           辅记点:事务ID越早越可见

定义实现/原因解决办法
悲观锁

每次操作都会被修改

mysql使用共享锁与排它锁,行锁
乐观锁只有在修改时才会加锁版本号或Cas(比较)提交
共享锁S读一行数据share on mode
排他锁X更新/删除一行

for update

duplicate on update

共享意向锁IS获取S锁前先获取此锁
排他意向锁IX获取X锁前先获取此锁
record lock单行锁
gap lock

间隙锁,不包括本身

使用普通索引锁定

记录不存在或查询一个范围

record lock + gap lock区间锁
死锁

两个事务都在请求同一个资源而持续等待无法释放过程

1,两个事务加锁的顺序不一致

1,编码时注意查询与写入的顺序

当前读与快照读

  快照读:读取的是记录数据的可见版本

     是通过MVCC与undo log版本链,读的是一个快照数据,RR是事务开启的第一个select,RC是每个select

   当前读:读取的是最新版本的数据

    以下语句会触发:

        select...lock in share mode (共享读锁)
   select...for update
  update , delete , insert

     是通过record lock 和 next-key lock实现,读的是最新的数据,并对读取的数据加锁

死锁

     多个事务在请求同一个资源而互相等待对方释放的过程

    查看方法:

//查看当前所有锁的情况
show status like '%lock%';
//查看当前进程
show processlist;
1:查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

2:查看当前锁定的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

3:查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 

    造成原因及解决方法:两个(或以上)的Session加锁的顺序不一致

           从操作数据库的动作来分析 

         1.Delete删除不存在的数据导致死锁

             容易造成区间锁

    解决方法:

       ①先检查记录是否存在,否则不删除。

      ③如果锁是gap锁,这种死锁需要将事务的隔离级别设置为read commit。

     ④对于等待锁的的会话使用innodb_lock_wait_timeout,防止过载。

    2,insert update时造成死锁

     解决方法:

1,使用mysql自有的方法

1,on duplicate key update 
2,使用replace来解决

2,使用redis自增Key

 3,  雪花算法

3,select for update(行锁) 或者 select share on mode

Innodb关键特性

   1,插入缓冲 insert buffer 由于非聚集索引即辅助索引是非连续的,所以在刷盘之前先进行判断是否在索引缓存页中,如果存在即直接插入或修改,如果不再就放入insert buffer中以一定频率和辅助索引页的节点进行合并再刷盘,内部实现也为一颗b+tree

   2,双写:写redo log和redo log副本,帮助灾难恢复

  3,自适应hash,监控表的查询情况,建立一个hash表,不需要建立hash索引

  4,异步I/O  预读,预写都是通过异步进行

  5,刷新邻近页:即为同时邻近脏页数据

  6,数据字典信息

Innodb索引:

    原理:使用B+树的结构,采用聚集索引的结构,叶子节点才会存放行记录或主键记录,而且索引与数据文件放在一起的,一张表就是一个聚集索引,myisam是非聚集

    优点:按索引排序,方便查询与order等操作,检索更快

     主索引:叶子节点存放的是行记录

   辅助索引:叶子节点存放的主键ID,有一个回表的操作,I/O次数为通常为(树高-1,ps:这个-1是因为根节点常驻内存)

   

     前缀索引:由于mysql的数据页为16K,一个页在索引树上为一个节点,如果要存放更多的索引值,就需要减少索引的长度,而本身索引的长度是有限制的小于767个字节,组合索引不能超过307字节,引出一个问题,为什么是307呢,还是与page 16K相关,因为要预留两对(fil page )Header,如果一个页不能存放一个索引值就退化成了链表,不符合设计思想

      覆盖索引:用一个sql说明,简单易懂:select a,b,c from user where a and b and c  (a,b,c)union_index

     PS:索引下推:(5.6后mysql服务器将在判断条件里有索引的列交给存储引掣进行判断,减少底层访问表的次数,也减少了mysql调用存储引掣的次数)

  常见问题 Innodb与Myisam的区别:

    Innodb是聚集索引,myisam是非聚集也就是索引与数据是分离的,每个叶子节点存放的是数据记录的指针,所以myisam不需要主键,就能直接查询到数据;Innodb支持事务与行锁,这是最为关键的两点

Mysql主从同步

  1,架构图

    

2,同步方式

     2.1 异步同步:在master上开启binlog功能一个I/O同步线程,在从库上配置,两个线程(一个IO线程,一个请求线程)

//主
server-id=1
log-bin=mysql-bin
//从
log_bin           = mysql-bin
server_id         = 2
relay_log         = mysql-relay-bin
log_slave_updates = 1
read_only         = 1

     2.2 半同步 master会等待slave至少发送一个写入relay log成功后提交,否则一直等待至超时(10s)

     2.3  多线程同步:slave多个线程从master同步binlog日志,再顺序写入    

 3,两种格式:statment (语句);raw(行记录),一个mixed(混合)

Mysql一些问题

    1,mysql如何解决主从一致性问题?

         关闭双1设置(binlog和redo log)写入到磁盘,如果是0只写入缓存等待按时间频率刷盘,如果是1会写入到磁盘

         减少从库查询压力,添加机器

         使用中间件(缓存)

         对实时性要求比较高的强制走主

    参考文档 深入理解InnoDB -- 架构篇 - 知乎

高性能Mysql主从架构的复制原理及配置详解_weixin_30311605的博客-CSDN博客

三,redis

   1,redis的五种常用类型及数据结构(string,list,hash,set,zset)

原创:redis中8种数据结构的底层数据结构源码详解

SDS simple synamic string:支持自动动态扩容的字节数组,遍历O(N),获取长度O(1),二进制安全,有一个特定的结束符\0
list :链表,双向,无环,长度计数,多态
dict :使用双哈希表实现的, 支持平滑扩容的字典 
zskiplist :附加了后向指针的跳跃表 
intset : 用于存储整数数值集合的自有结构 
ziplist :一种实现上类似于TLV, 但比TLV复杂的, 用于存储任意数据的有序序列的数据结构 
quicklist:一种以ziplist作为结点的双链表结构, 实现的非常不错 
zipmap : 一种用于在小规模场合使用的轻量级字典结构 

String:

list:

hash:

set:

zset有三种还有一种是用hash(字典)

  sds做为string的底层结构,buf为了一个byte数组,再用柔性数组(伸缩性)来解决容量问题

  

  list 做为list的底层结构

hashTable做hash的底层结构之一

skiplist 跳表  用两张表

ziplist 压缩表作为 list,hash,zset的底层结构

在这里插入图片描述

intset 整数集合作为set的底层结构之一

在这里插入图片描述

2,缓存击穿,穿透,雪崩和一致性问题

    2.1,穿透:缓存里没有,数据库里也没有。解决:数据的合法性、安全性进行校验;布隆过滤器

             击穿:缓存里没有,数据库里有。解决:热点Key永不失效;互斥锁

             雪崩:缓存里的key大面积失效。解决:随机过期时间;主动更新数据

           一致性:延时双删(在更新数据库前和后都删除缓存数据,再加上一个延时时间);异步中间件订阅binlog进行一个补偿机制

3,缓存过期策略

      3.1 定时删除:redis每隔100ms随机检查是否有过期Key

      3.2 惰性删除:在访问到这个Key时检查

      3.3 淘汰机制:lru(最近最少使用)

        noeviction:不足时报错,无法写入

    allkeys-lru: 不足时,在所有Key中最近最少使用的删除

    allkeys-ramdom:不足时,在所有Key中随机删除

    volatile-lru: 不足时,在过期Key中最近最少使用删除

        volatile-ramdom:不足时,在过期Key中随机删除

    volatile-ttl:不足时,在过期Key中删除更早的

4,缓存主从+哨兵

    4.1,主从

      概念:一般来讲redis的服务器搭建分为主从,分布式,而哨兵单独存在是没有意义的

      原理及实现:

         1,先在从节点redis.conf中配置:slaveof 主数据库ip 主数据库port
  先启动主节点,再启动从节点即可-------准备阶段

                    2,从节点发送sync(psync)命令,主节点收到后无条件触发RDB持久化并保存在此期间新的写命令

                    3,当快照完成后,主节点将RDB文件和命令一起发送给从节点

                    4,从节点会加载快照文件和命令进行同步

             核心机制:

                1,offset 偏移量

                2,backlog 1M用来做增量复制留存记录页

                3,run id :主从都会写

                4,psync:同步命令

               5,heatbeat机制:主节点10s一次,从节点1s一次

       4.2,哨兵

            作用:

             1.监控主数据库和从数据库是否能够正常运行
             2.主数据库出现故障时自动将从数据库转换为主数据库。

            在这里插入图片描述

           实现:由三个定时脚本

  • 每隔10s向主数据库和从数据库发送info命令,检查节点信息
  • 每隔2s向主数据里和从数据库的_sentinel_:hello频道发送自己的信息。
  • 每隔1s向所有数据库节点和所有哨兵节点发送ping命令

          选举:两个选举,一个是对节点故障的选举;另一个是哨兵自己本身的故障选举,哨兵为奇数方便投票

主节点下线:

  • 选出领头哨兵
  • 领头哨兵从在线的从数据库中,选择优先级最高的从数据库。优先级可以通过slave-priority选项设置。
  • 如果优先级相同,则从复制的命令偏移量越大(即复同步数据越多,数据越新),越优先。
  • 如果以上条件都一样,则选择run ID较小的从数据库

哨兵自我选举

  • 发送主数据库客观下线的哨兵向每个哨兵命令,要求对方选择自己为领头。
  • 如果没有选择过其他哨兵,则会同意请求
  • 如果发现有超过半数,且超过quorum的哨兵同意自己的请求,则自己就是哨兵领头。

   4.3,分布式系统数据一致性

         首先一致性的特性(ACID)即一致性,隔离性,持久性,原子性。另外CAP即一致性、可用性、分区容忍性

         一致性协议

             两阶段提交:两个阶段:准备阶段(投票反馈阶段)和 提交阶段(执行阶段)

             带来的问题:1,单点故障

                                   2,网络引起的消息丢失和阻塞

            三阶段提交:canCommit prepareCommit  doCommit。解决了阻塞问题

          RAFT协议:leader选举,日志复制,节占监控

           互联网公司常用:TCC本质上在两阶段上增加了一个取消的流程即Try Comfirm,Cancel,保证高可用性

     4.4,Redis 问题

        aof文件过大,如何处理:重写 bigre

       大key删除:set->sscan hash->hscan hdel 分批删除

四,PHP&Go

     PHP hashtable packed array

     Go gouroutine(协程),采用CSP的方式(在通信中共享内存),内部实现原理为MPG,大意是:M(内核进程),P(逻辑处理器),G(协程),Go会将G首先放入一个globle队列,然后分配到一个P的local队列,内核M进程会不断地去取G,P切换栈空间进行执行

    channel 是 goroutine 之间通信的一种方式,可以类比成 Unix 中的进程的通信方式管道。

五,MQ

  Kafka 与Mq:

  rabbitmq 如何保证成功发送消息,tranction comfirm ack(默认)

  如何保证成功消费消息   ack确认

   保证顺序性?:一个queue对应一个consumer

   

六,数据结构&算法

     一,归并算法

        思想:利用递归,先拆分、后合并、再排序,其实就是一颗二叉树

         步骤:时间复杂度O(N*logn)

  1.  先均分成两个数列
  2.   递归上一个步骤,直到只有一个元素
  3.  父数列合并两个子数列并排序,递归返回数列

//归并
<?php
  function mergeSort($arr)
  {
      $count = count($arr);
      if ($count == 1) {
          return $arr;//只有一个
      }
      $mid = (int) ($count/2);
      $left = array_slice($arr,0, $mid);
      $right = array_slice($arr,$mid);
      $left = mergeSort($left);
      $right = mergeSort($right);
      $arr = merge($left,$right);
      print_r($arr);
  }
  function merge($left, $right)
  {
      $newArr = [];
      while(count($left) && count($right)) {
          $newArr[] = $left[0] < $right[0] ?  array_unshift($left) : array_shift($right);
      }
      return array_merge($newArr, $left, $right);
  }
  $arr = [10,1,3,2,7,8,6,5,4];
  mergeSort($$arr);
?>

二,快速排序

     思想:确定基线,将大于基线的往后,将小于基线的往前,左右分别递归

     时间复杂度O(N*logn)

function quickSort($arr)
  {
      $base = $arr[0];
      $left = $right = [];
      for ($i =1;$i<count($arr);$i++) {
          if ($arr[$i] < $base) {
              $left[] = $arr[$i];
          } else {
              $right[] = $arr[$i];
          }
      }
      $left = quickSort($left);
      $right = quickSort($right);
      return array_merge($left,[$mid], $right);
  }

三,单链表反序

<?php
class listRevert{
  pubic function setNode($value){
    $this->next = $value;
    }
  function getNext(){
    return $this->next;
   }
//反序核心代码
##单链表反序
function revert($head = null)
{
    if (empty($head)) {
        return $head;
    }
    //取出头变成尾
    $pre = $head;
    $cur = $this->getNext();//取出下一个节点
    while($cur != null) {
        $next = $this->getNext();
        $this->setNode($cur); //设置当前节点
        //交换
        $pre = $cur;
        $cur = $next;
    }
    $this->setNode(null);
    $head = $pre;//将尾变为头
    return $head;
    
}
}

四,冒泡

<?php
// 这里以一维数组做演示
$demo_array = array(23,15,43,25,54,2,6,82,11,5,21,32,65);

// 第一层for循环可以理解为从数组中键为0开始循环到最后一个
for ($i=0;$i<count($demo_array);$i++) {
    // 第二层将从键为$i的地方循环到数组最后
    for ($j=$i+1;$j<count($demo_array);$j++) {
        // 比较数组中相邻两个值的大小
        if ($demo_array[$i] > $demo_array[$j]) {
            $tmp            = $demo_array[$i]; // 这里的tmp是临时变量
            $demo_array[$i] = $demo_array[$j]; // 第一次更换位置
            $demo_array[$j] = $tmp;            // 完成位置互换
        }
    }
}

七,系统架构

    redis 高可用方案

    nginx 高可用方案

    mysql高可用方案

   mq高可用方案

八,GO

巨人的肩膀:

https://segmentfault.com/a/1190000019835802

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值