Git Product home page Git Product logo

interview_summary's Introduction

一. Python

  1. Python 的优点和缺点 优点:

    • 易扩展:使用pip便可以轻松安装相关的库,而且方便调用。
    • 语言融合性:python可以方便的调用其他的语言编写的代码,也方便被其他的语言调用,胶水性语言。
    • 开发速度快:大量的,成熟的库使得python在写业务功能的时候拥有非常快的速度。
    • 简单,容易学习:语法简单,非常适合编程新手学习。
    • 可读性:python的语法简单,造成在阅读python 的代码的时候并不需要很多的经验,方便理解代码。
    • 面向对象:python支持面向对象的编程范式,也支持面向过程的。
    • 开源:python是免费提供的,不仅仅是免费的试用,而且可以方便的获取python的源码,而且可以根据自己的需求修改。
    • 跨平台性:只要不使用涉及带平台底层的库,一次编写代码,便可以在各个平台运行。
    • 解释性代码:代码运行过程不是一次性编译的时候转换成二进制的运行程序,而是在运行的时候一行行的解释代码成二进制命令,一行行的运行,所以调试的时候更方便一些。

    缺点:

    • 运行速度慢:解释型语言,代码运行的时候速度慢,性能难受。
    • Web型:python是一个出色的服务端语言,但是在客户端的编写上基本上是见不到python的。
    • 设计限制:动态类型,方便理解和阅读,但是同时也容易出现bug。
    • 数据库访问层不够发达:相对于jdbc 和 odbc,python的数据库访问不够完美,所以大型企业很少试用。
    • 简单:太过于简单了,所以新手学习了python之后在学习其他的语言会很吃力,而且会排斥其他的语言。
  2. 深拷贝和浅拷贝的区别
      用指针的概念解释会比较好,深拷贝是将A的数据里面的值拷贝到B,浅拷贝就是将A的指针拷贝到B,一个拷贝的是值,一个拷贝的是引用。

  3. 列表和元组的区别
      列表是可以变动的,元组是不可变动的,list和 tuple是可以相互转换的。不是很清楚元组存在的意义,实际上元组可以干的活,列表全部可以干,但是列表可以干的,元组不可以干。

  4. Python 三元运算

    a, b = 2, 3  
    min = a if a < b else b
    
  5. Python 中的多线程和多进程
      Python 的多线程可以通过自带的threading 库实现,但是python 的GIL(全局解释器锁)导致python的多线程实际上同时只会有一个线程运行的,python3对GIL的获取方法做了改动,采用计时器的方式来改变GIL使用权,cpu密集型的处理有所改善,但是还是不够好。
      Io密集型的情景下是可以使用多线程的,cpu密集型的情况下不建议使用多线程,cpu密集性实际上也不建议使用python处理,python运行的效率很低,完全不适合cpu密集性的代码。多核多线程情况下使用python,效率会更低下,多个cpu核去获取GIL效果会更差,所以python一般使用多进程处理,每个进程只使用一个线程。Python 一般是用subprocess 模块处理多进程, 如果只使用linux的情况下可以使用os.fork()建立新的进程。
      还有一种方法,是多种语言的配合使用,将cpu计算密集性的代码使用c,c++等效率高的语言去写多线程的计算模块,使用python去写业务性代码,并调用其他代码,两种代码结合使用会更舒服的。

  6. Python的继承
      Python 支持 多层继承,就是 son 的father 也可以有father,一层层的继承下来,也支持多多重继承,就是一个son可以有多个father。
      father的方法和属性son是都可以调用的,son类内部使用super调用,son类的对象调用的话就像自己方法一样调用。多重继承的情况下,调用一次super.a(),可以同时调用每个father的方法a方法,只要该father 有,也可以直接使用father的类名来调用方法。重写就是在son里面重新定义father的方法和属性就可以了。
      Python不支持方法重载,可以使用默认传参,或者*args 或者 **kwargs 来实现类似重载的方法,或者是@ classmethod来实现的。

  7. Python的内存管理
      Python 使用一个私有的堆空间来保存所有的对象和数据结构,开发者是无法直接访问,是由解释器来管理它。 每一个对象被创建的时候,便会对该对象开始计数,计数会因为该对象的每一次被函数调用,被加入到容器中,或者赋值给其他的对象而增加,相应的从每一次函数结束,容器中移除,调用对象的销毁,或者重新赋值而减少,等到该计数为0的时候,就是该对象应该被销毁的时候。
      循环调用的对象,a调用b,b调用a,会使用循环垃圾回收器来处理,当没有任何其他的方式引用 a或者b的时候,a和b同时销毁。
    Python将多有的对象分级,分成0,1,2三代,所有新创建的对象会放入到0代中,当某代对象在经历一次垃圾回收之后还存活的话,就会放入到下一代,在经历一定次数0代的垃圾回收,才会启动0代,1代的扫描清理, 同样,在经历一定次数的1代的垃圾回收之后才会启动0,1,2代的扫描清理。
      Python是有内存池的,内存池是针对小对象的(大小小于256bits),被销毁的对象的空间并不是返回给操作系统的,而是放入到相应的内存池里面的,整数,浮点数,字符串,list等都是由独立的内存池,这些内存池相互之间是不共享的,整数内存池里面的内存是不能用来申请浮点数的。
      小数据(1-256)使用的内存在申请之后是不会销毁的,其他对象再次使用该数据的时候,直接引用之前申请的内存。
      常用字符组成的字符串在没有销毁之前,再次申请的情况下是不会重新申请内存的,而是共用内存。
      对象大小大于256个bit的时候是直接从操作系统的内存空间申请的空间。

  8. Python里面的help() 和 dir() 方法
      这两个方法都是python的内置方法,也都是用来了解函数或者模块的。
      Help() 方法显示的是函数的用途和详细说面,一般显示的是固定的方法注释的内容,成熟的模块一般都会在这些注释中写明调用方法和使用场景,还有调用的效果。
      dir() 方法在不带参数的时候显示的是当前范围的变量,方法和定义,带参数的时候显示的是参数的属性和方法列表。

  9. Python在退出的时候,是不是释放了全部内存
      并不会,循环应用的对象,还有引用自全局命名空间的对象并不会被完全释放。
      调用的其他语言写的代码的内存,并不会被python解释器控制,有其他语言自己处理。

  10. Python的传参 *args 和 **kwargs 的含义和区别
      *args 和 **kwargs 都是在不知道想该方法传递固定参数的情况下的使用的。
      *args 是传递的是list 或者 puple。
      **kwargs 传递的是一个dict,也可以在传参的时候多个k=v的方式传参。

  11. Python 负索引和数组的切片
      负索引和正索引是一样的,都是用来表示list的index的,不过正索引是从左边计数的,负索引是从右边计数的。
      数组的切片是[:]的方式实现的,冒号两边就是list的开始和结束索引。
      数组的切片也可以是[::]的方式,前两个参数和两个的是一样,也是list的开始和结束的索引,第三个参数的符号表示 正序还是倒序,正整数就是正序, 负整数就是倒序, 第三个参数的绝对值就是隔几个获取一个值, 比如[::2] 就是获取index为0, 2, 4, 6, 8 …… 的值,[::3] 获取的就是 0, 3, 6, 9 ……。

  12. Range 在python2 和 python3 的区别
      Python2 的range 返回的是一个list,在python3 返回的是一个range的对象,该对象是可迭代的,不是list对象,但是该对象是可以转换成list的。

  13. Python的闭包特性
      内嵌函数,在一个函数的内部再定义一个新的函数,这个新的函数只能在前面一个函数的内部调用。
      闭包就是要求就是,首先要有一对内嵌函数,内嵌函数必须调用外部函数的参数或者变量,而且外部函数必须返回改内嵌函数,而不是参数,或者变量,或者什么计算结果。
      闭包本质是一个函数,只要该闭包没有被销毁,那么该闭包里面包含的部分变量可以一直保存下去。闭包避免了使用全局变量,将函数和他操作的部分数据关联起来,就类似于面向对象的类一样,一般来说一个类只有一个方法的时候,就可以使用闭包。
      常见的闭包,装饰器,单例模式,非面向对象语言的实现的面向对象的方式。

  14. Python 中不常见的运算符 //, % 和 **
    % 就是取余,和其他的语言一样的。
    // 是向下取整, 就是 (a-a%b)/b。
    ** 就是取幂, a**b 就是 a。

  15. 为什么不建议一下划线作为标识符的开头
      Python是没有私有变量的概念的,所以约定俗成的将下划线开头的变量当成私有变量,所以最好不使用使用下划线开头标识符表示有变量的。

  16. 迭代器和生成器的区别
      迭代器协议,对象需要提供next()方法,该方法返回迭代中的下一代,要么反返回一个StopIteration 的异常,来终止迭代。实现内置函数__iter__() 和 next() 方法就可以实现对象的迭代器。
      可迭代的对象,list, tuple, dict, str 等。
      生成器是用来创建类似迭代器效果的一个非常简单的工具,只需要在返回数据的时候使用yield语句,便可以创建一个类似于迭代器的效果,每次调用使用生成器的函数,该函数都会在上一次中断的地方继续运行,并返回结果,同时将运行参数和环境保存下来,提供给下一次使用。
      迭代器一般是针对一个类似于可迭代对象的容器。
      生成器一般是针对类似于一个循环的过程中,每一次循环都需要返回一个结果的。

  17. 装饰器的作用和常用场景
      装饰器实际上是一个闭包,他的作用就是在不修改函数代码的情况下添加额外的功能。
      装饰器的常用场景,函数的运行时间计算,函数的运行次数(web api接口的计数器 ),flask的路由传参,函数的运行的日志,事务处理(多个函数处理过程必须同时运行成功,或者同时运行失败),缓存处理,权限的校验等功能。

  18. 猴子补丁是什么
      猴子补丁是指运行的时候给某一个对象添加或者替换属性。
      猴子补丁可以方便代码的功能的编写,方便测试,但是也容易搞乱源代码的关系,不容易理解,也不够优雅。不建议使用。

  19. @property,@classmethod, @staticmethod
      三个都是用来标记特殊方法的装饰器。
      @property 是表示将方法当成属性使用,可以用调用 对象.方法名 的方式运行该类对象.方法名()。
      @staticmethod 是指 全局静态方法,直接使用 类名.方法名() 调用。
      @classmethod 是指 类方法,类方法必须将类对象当成第一个传参,就类似普通类方法的self一样,可以只用类名.方法名()调用,也可以使用 对象.方法名()调用,实际上这个方法一般是用来类对象申明方法的重载。

  20. Python的内置方法 call() 的作用
      在类中声明__call__() 方法会让这个类申明的对象可以当场函数去使用,当这个对象当成函数使用的时候,实际上调用的就是__call__() 方法。

  21. Python的可变对象和不可变对象
      int, string, float, tuple 都是不可变对象,在这些类型的变量发生变动的时候,是原内存的内容不变,重新申请内存保存新的值,然后这些对象重新指向新的内存,可以理解城这中就是,值不变,该变量的指针发生了变动。
      list,dict 是可变对象,是修改时,指针不变,指向的内存的值发生变动。

  22. Python is 和 == 的区别
      is 判断的是两个对象的id是不是一样的,实际上就是指针是不是一样的。
      == 判断的是两个对象的值是不是一样的。

  23. 类变量和实例变量
      类变量是所有实例之间共享的值,他们是不会单独分配给每个实例。
      实例变量是每个实例单独有的变量。

    class Test(object):
        num_of_instance = 0
        def __init__(self, name):
            self.name = name
            Test.num_of_instance += 1
    

      这个例子中 num_of_instance 就是类变量,name就是实例变量。

  24. Python的自省
      实际上就是反射,就是可以通过一些方法获取到对象的属性和方法,对象的类型,像 type(), dir(), getattr(), hasattr(), setattr(), isinstance()。

  25. 鸭子类型
      “鸭子类型”的语言是这么推断的:一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)。
      “鸭子类型”没有任何静态检查,如类型检查、属性检查、方法签名检查等。
      “鸭子类型” 适用动态语言 和 某些静态语言。
      比如说A对象有song() 方法,B对象也有song() 方法,那么在调用song() 的方法的时候,可以直接将B当成A使用,而不会管B到底是不是A。

  26. 单例模式
    Python的单例有多种实现方式:

    1. new 方法实现
    class Singleton(object):
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                orig = super(Singleton, cls)
                cls._instance = orig.__new__(cls, *args, **kw)
            return cls._instance
    
    class MyClass(Singleton):
        a = 1
    
    1. 类变量的方法实现,类变量是所有实例共享的
    class Borg(object):
        _state = {}
        def __new__(cls, *args, **kw):
            ob = super(Borg, cls).__new__(cls, *args, **kw)
            ob.__dict__ = cls._state
            return ob
    
    class MyClass2(Borg):
        a = 1
    
    1. 装饰器实现
    def singleton(cls):
        instances = {}
        def getinstance(*args, **kw):
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
    
    @singleton
    class MyClass:
    ...
    
    1. 多文件,import方法实现。
    # mysingleton.py 文件  
    class My_Singleton(object):
        def foo(self):
            pass
    
    my_singleton = My_Singleton()
    
    # to use 文件  
    from mysingleton import my_singleton
    
    my_singleton.foo()
    
  27. 协程
      协程实际上就是执行一段代码的时候,中断该程序运行,转而运行其他的子程序,等适当的时候在返回回来继续执行,python的协程是通过生成器的方式来实现的。由于协程实际上还是单线程,共享数据不需要控制锁,所以性能优势很明显。   传统的生产者-消费者是一个线程写,一个线程取,通过队列来传递和控制。而改用协程之后,生产者产生消息后,可以直接yield跳转到消费者使用消息,消费者执行完毕之后,在切换都生产者生产,这样的效率有极大的提升,而且实际上还是单线程运行的。

  28. read(), readline(), readlines(), xreadlines()
      read() 是一次性读取所有的文件内容,返回一个字符串。
      readline() 是读取一行的内容,返回一个字符串,多次调用该方法以遍历整个大文件。
      readlines() 也是读取文件的所有内容,但是以行为单位,放置到一个列表中,返回一个列表,一次性读取,不适合处理大文件。
      xreadlines() 返回的是一个生成器,不是一次性处理,是在每次运行的时候才,和readline很像,但是不需要每次读取下一行的时候都调用一遍, 可以自己实现循环 。

  29. python2 的range, xrange, 和 python3的range
      python2的range 返回的是一个数组。
      python2的xrange 返回的是一个生成器。
      python3的range实际上就是python2的xrange,返回的是一个生成器。

  30. 字典式推导、列表式推导
      列表式推导,就是使用[ for in if ]的方式处理生成列表,直接在在[]里面实现循环,并且判断。使用[] 得到的是一个列表,使用() 得到的是一个生成器。
      字典是推导,就是使用{k:v for in if}的方式处理成字典的。

  31. 新式类和旧式类
      Python3 取消了经典类,默认都是新式类
      Python2 默认的是经典类,只有使用Class Person(object):pass 的方法声明的类才是新式类。
      新式类和旧式类的区别最大的实际上是多继承的搜索顺序的改变。
      新式类采用的是并非是广度优先,而是C3算法。在同根节点的同级节点时候使用从左到右搜索,不同根节点的同级节点的时候,会在一个和紫薯搜索完了之后搜索到父级节点。
      旧式类采用的是深度优先搜索,从继承树的低到上的搜索方式。

  32. 作用域
      实际上就是一个变量声明之后可以被访问的范围。
      Python的作用域是静态的,声明的位置决定该变量可以被访问的范围。
      值得注意的是在if-elif-else、for-else、while、try-except\try-finally等关键字的语句块中并不会产成作用域。也就是在改代码块结束之后,可以访问到改代码块中声明的变量的。
      不同的作用域也决定代码在运行的时候使用的是什么变量。
      LEGB是代码运行过程中用来判断name是在那个作用域里面找到的,LEGB的顺序是 Local, enclosing, globals, __buitins__。

    • locals 是函数内的名字空间,包括局部变量和形参。
    • enclosing 外部嵌套函数的名字空间(闭包中常见)。
    • globals 全局变量,函数定义所在模块的名字空间。
    • __buitins__ 内置模块的名字空间。

二. Linux

  1. 常用命令 cd ls ll mv ps top fg vim rm wc kill which whereis cat mkdir touch tail less ln chmod chown

三. Mysql

  1. 建表六大约束
  • 主键约束
  • 外键约束
  • 唯一约束
  • 非空约束
  • 默认约束
  • 自增约束
  1. tinyint,smallint,mediumint,int,bigint区别
    都是整数类型,但是存储的字节数不同,保存整数的大小范围也不一样 tinyint 保存占1个字节,有符号范围是 -2^7 – 2^7-1,无符号范围是 0 0 - 2^8 -1 smallint 保存占2个字节,有符号范围是 -2^15 – 2^15-1,无符号范围是 0 - 2^16 -1 mediumint 保存占3个字节,有符号范围是 -2^23 – 2^23-1,无符号范围是 0 - 2^24 -1 int 保存占4个字节,有符号范围是 -2^31 – 2^31-1,无符号是 0 - 2^32 -1 bigint 保存占8个字节,有符号范围是 -2^63 – 2^63-1,无符号范围是 0 - 2^64 -1

  2. 存储引擎类型
    MyISAM, mysql5.1 之前的默认存储引擎。 优势是:读取是速度快,占用资源少。 劣势是:不支持事务;不支持行级锁;只有表级锁,更新数据的时候锁定整个表,极大地降低了并发性能,而且读写会阻塞;只能缓存索引,不能缓存数据;不支持外键约束,外键查询只能全文索引。 适合场景,单一业务场景,不存在太多的表关联,读也频繁但是并发量低。而且读的量比写的量高的。 InnoDB:mysql5.1 之后的默认存储引擎。 Innodb 是一个事务型存储引擎,有行级锁和外键约束。会在内存中建立缓冲池,用来缓存数据和索引,但是不会保存表的行数。读取数据默认不会锁表,有主键的自增约束 适合出现在业务复杂的场景,大量的表与表关联的场景,大量的并发的数据更新场景。而且非常适合可靠性要求很高的场景。 Innodb由于事务的原因,拥有了提交,回滚,数据库崩溃回复等能力,重做日志,可以通过日志方便的恢复数据库 Memery,堆内存,实际上就是用内存创建表,使用默认的hash索引,由于数据保存在内存中,读写速度都非常快,保存的时候保存在一个磁盘文件里面,关闭服务器之前如果没有保存数据的话,数据将会丢失。 适合做统计的中间表,可以高效的从内存中分析得到最终结果,可以保存的数据比较小,而且具有临时性。 Merge 实际上是多个相同的MyISAM表的集合,同一个表大量的数据的时候,是可以将一个表分成多个MyISAM表,然后再聚合成一个Merge表做数据查询。 主要就是innodb和MyISAM的区别。 Innodb支持事务,而MyISAM不支持。所以MyISAM在增删改查的时候速度较快,Innodb在不涉及事物的时候,性能较快,设计的时候性能较低,但是事务支持回滚等功能。 Innodb支持行级锁,MyISAM只支持表级锁。所以Innodb在并发的时候效率要远高于MyISAM。 行数保存,innodb不支持行数保存,查询的时候需要全表扫描,而MyISAM不需要 索引存储。Innodb 索引适合数据捆绑保存的,而MyISAM索引和数据是分开的。MyISAM的缓存的索引要多很多。 两个表的数据备份,innodb 不支持 load table from master的方式复制表,导致数据备份和转移比较麻烦,数据量大的时候更是痛苦。

  3. 事务
    事务拥有四个特性:

  • 原子性:事务作为一个整体被执行,一个事务里面的操作要么全部被执行,要么全部不执行。
  • 一致性:事务应该确保数据库的状态,从一个一致的状态转换成另一个一致状态,一直状态就是数据库中的数据应蛮族完整性约束。
  • 隔离性:多个事务并发的时候,每个事务的执行是不会相互影响的
  • 持久性:已提交的事务对数据的修改是会永久保存在数据库中的
  1. 数据库的隔离状态
    当多个线程都开启事务操作数据库的时候,数据库系统需要做到隔离操作,以保证各个线程获取的数据的准确性。不考虑数据库隔离性的情况下,会发生以下几种状态:
  • 脏读:A事务处理过程中读取了B事务多次修改而未提交的中间过程的脏数据,
  • 不可重复读:A事务在多次读取某一数据的时候,B事务修改了该数据并提交,导致A多次读取的数据结果不一致
  • 幻读:A事务将某一数据从1修改成2,B又从2修改到1,C事务循环读取的时候,读取到了一次2,如同幻觉一样 Mysql数据库提供四种隔离级别 Serializable 所有事务串行运行,不可并发 Repeatable read 一旦有事务开始读取某数据,其他事物就不可修改该数据(mysql默认) Read commited 不可读取未提交的数据,可避免脏读 Read uncommitted 最低级别,什么都无法保证 隔离级别越高,数据安全性越高,但是性能越低
  1. 索引
    全文索引 只有MyISAM 引擎支持,只能在char,varchar,text中使用,主要是用来解决like之类的模糊查询效率低的问题的 Hash索引 就是通常意义的key-value的hash,hash索引,hash索引在定位==的时候效果极好,但是对于范围查询,>, < 等运算是无法处理的,而且hash无法避免排序操作,在使用组合索引的时候无法使用前面的一个或几个字段的来查询。Hash无法避免全表扫描,hash在hash值相等的情况下,效率极其低下 Btree索引 将索引值按照一定的算法,存入到一个平衡查找的树形的数据结构里面,每次查询都是从根节点到叶子节点。 所有的叶子节点都是在树形结构的最后一层。 B+tree索引,Btree的改编版本,B+tree的key只保存在也叶子节点,而且每个叶子节点都有一个有序链表的指针。 Rtree索引 Rtree的优势是在范围查找上面。 普通索引 …… 唯一索引 和普通索引的区别就是索引值不允许出现重复,但是允许出现空值 主键索引 专用与主键的索引,唯一索引,但是不允许出现空值,一般在建表的时候就会创建的 组合索引 多个字段组合的索引,使用组合索引遵循最左前缀集合。 全文索引

  2. Expain
    关键字段,id,type,key,rows,extra id 显示是每个子语句的执行顺序,id值越高优先级越高,越早被执行 type 显示的是执行语句的访问类型,该字段表示语句运行之后,是否是直接匹配到,还是直接索引一次,还是扫描索引,还是没用使用索引,还是便利全表。 key 显示的是使用的索引,如果没有使用索引,显示的就是空 rows 根据统计信息和索引使用情况,显示找到数据索要的读取的行数 extra 显示的是执行的时候显示的额外信息,就类似于DEBUG信息一样

  3. 海量数据存储优化
    sql 和 索引优化,根据索引和explain结果优化查询语句,尽可能不会出现慢查询。 添加缓存,memcached,redis等方法添加内存缓存 主从复制,读写分离,可以自己在业务层添加处理 使用mysql自带的分区表,根据分区原理优化sql语句,避免全面扫描所有分区 垂直拆分,根据系统的耦合性,将大的业务系统分割成多个子系统。每个子系统根据自己的数据特性优化自己的引擎,索引,sql语句之类的。 水平拆分,针对数据量大的表,选择合理的sharing key,将一个表分成多个小表,sql语句也要尽可能优化,避免扫描全部的表

  4. 连表查询
    在真正做业务的时候不建议试用连表查询,这样有可能会出现慢查询,从而导致数据库卡住了。但还是需要了解一下的。
    嵌套查询:试用多个sql语句,将一个sql的查询结果作为外层sql的查询条件查询 select * from A where A.id in (select id from B where B.name = “李三”)
    内联查询:一次查询多个表,使用多个表格的相同的字段作为连接手段。
    比如: 隐式内联: select A.* from A, B where A.id = B.id and B.name = “李三”;
    Inner join(显示内联): select * from table1 inner join table2 on table1.id = table2.id where table2.name = “李三”;
    Left join(外联,左): select * from table1 left join table2 on table1.id = table2.id,返回table1 的符合条件的行数全部显示出来,没有和table2 关联的行,数据显示为空,有关联的行,显示table2的数据
    right join(外联,右):select * from table1 right join table2 on table1.id = table2.id,返回table2 的 符合条件的行数全部显示出来,没有和table1 关联的行,数据显示为空,有关联的行,显示table1的数据。
    full outer join(外联: 全): select * from table1 full outer join table2 on table1.id = table2.id 返回table1 和table2 的 所有行,一个表在另一个表里面没有匹配的行的时候显示空。

四. Nginx

  1. nginx 负载均衡是怎么实现的
    轮询:根据请求时间顺序分配不同的后端服务器 加权轮询:更具服务器性能,配置每个服务器的权重,根据权重分配每个服务器的访问量 least_conn 最少连接,新来的访问,分配给当前连接量最小的服务器 ip hash:根据ip的hash结果分配访问后端服务器,每个访客访问的后端服务器都是固定的 响应时间分配(第三方):响应时间越短的服务器,分配的访问量越多 url hash(第三方):更具url的hash的结果分配访问服务器

  2. nginx优势
    高扩展,跨平台,高可靠,低内存消耗 单线程非阻塞事件处理:并发处理的数量高 内置的服务器检查机制,down的服务器,后期的请求就不会在发送到down的服务器上 内存消耗小 nginx可以动静分离,静态文件处理快,耗费内存少 代理,不管是正向的代理还是反向的代理, Master/worker进程,master专用管理,worker是实际工作线程 负载均衡

  3. nginx 怎么配置负载均衡
    在配置文件里面使用upstrem 配置

  4. nginx 参数调优
    work_process:进程数量,不超过cpu的总核数 work_rlimit_nofile: nginx最大打开文件数量的限制,但是也受系统可以打开的最大打开数量限制 work_connections: 设置work进程可以同时打开的最大连接数,但是这个参数也受系统socket连接数限制 use: linux 应该是 epoll,允许单个线程处理多个客户端请求 keepalive_timeout:配置keep alive 的 超时时间 keepalive_requests:配置keep alive 的可以发送的请求数量 reset_timeout_connection: 服务器发送玩应答之后关闭连接 client_body_timeout 客户端请求超时时间,默认60s

  5. uwsgi工作原理
    wsgi 是python语言定义的,web服务器和web应用程序之间沟通的简单通用的接口,flask 和 django都自带wsgi的服务器,但是实际性能不好,所以生产环境一般都是nginx+uWSGI+相应的框架配合使用。 uWSGI 是实现http, uwsgi, http等协议的web服务器

五. Docker

  1. Docker 镜像怎么精简
    首先精简原始镜像,尽可能选择体积小的,而且功能齐全的原始镜像; 在就是修改dockerfile文件,将镜像里面的Run apt yum等命令合并成一行,清理和我们系统无用的组件,删除安装过程形成的中间文件,比如说pyc文件,安装包文件。 使用upload 导出成压缩包文件。

六. Redis

  1. Redis 简单原理
    Redis是一个基于内存的key-value数据库。 redis会周期性的将内存的数据写入到磁盘里面。 Redis速度极快,因为Redis完全基于内存,而且所有的数据结构都是专门设计的,单线程串行,避免上下文切换和多进程多线程切换所造成的消耗,不需要考虑资源锁,多路I/O复用模型,就是使用单线程处理多个连接请求,减少i/o 处理的消耗,实际上就是某路等待i/o的时候同时处理其他路的连接。官方给出的数据是每秒10W+。

  2. Redis数据结构

  • String, 普通c语言字符串实际上就是一个char的数组,而redis的string保存的有char数组的长度,还有char数组空闲的长度。 这样可以避免在获取长度的时候对char数组的遍历。 还在每次字符串处理的时候检测字符串长度,避免溢出。 重新分配内存的时候,并不是分配的刚刚好,而是会多分配一定的空间,可能在下次少量添加字符串的时候,不用分配空间,以减少分配空间的次数。 缩小字符串的时候,不会主动释放空间,避免下次扩充的时候需要再次分配空间,知道调用相应的api来释放剩余空间 有len属性,可以避免字符串中间出现的空字符串照成的字符串中断
  • List: 没有环的双向列表,而且节点保存的value不是固定类型的,保存有list的len,而且保存有tail和head节点
  • Hash:和普通的hash不同的是,当hash值相同的时候,value并保存的是一个单项连表结构,而不是普通hash的value,这样解决了普通hash的键值冲突的问题。在对hash处理的时候,hash列表的长度会发生变动,redis的处理是逐步重新散列的方式处理。Hash是有两个table的,开始重新散列之后,每次操作hash的时候,将一条数据从主表移除,hash保存到附表里面去,直到主表的为空,再将主表释放,将附表定义成主表,再重新申请空间形成附表。
  • Set:实际上就是就是一个value为空的hash,通过hash的方式去重
  • Sorted Set,有序集合,实际上就是更具优先级排序的集合。实际上保存的数据结构是一个基于插入排序跳跃表。跳跃表实际上是一个多级链表,每级链表都是一个有序链表,最底层链表保存所有节点。上层节点集合是下层节点集合的子集,每个节点都指向同层的下一个节点,也指向下层的同一个节点。 redis 所有的对象分配内存都是通过redis自己实现的内存分配方式实现的,和普通内存分配方法的区别就是会在内存快的前面分配一块内存,来保存该对象的长度。

七. 系统

  1. 线程和进程
    进程是资源分配的基本单位,比如是内存,磁盘空间,i/o等的资源分配。 线程是进程中执行运算的最小单位,也是cpu调度的基本单位。 一个线程只能属于一个进程,一个进程可以有多个线程,但是必须要有一个线程。同一个进程里面的多个线程是共享该进程的所有资源的,比如内存堆存储,代码,常量,全局变量和静态变量,但每个线程都有自己的内存栈存储,保存的是局部变量和临时变量。 进程间通讯必须要建立相应的通讯机制,线程间的通讯只需要通过读取和写入进程变量来控制。

  2. 进程间通讯

  • 管道:一种半双工的通讯方式,数据只能单项流动,只能父子进程通讯,一种很古老的通讯方式。
  • 命名管道,也是一种半双工的通讯方式,但是允许没有关系的进程之间通讯
  • 信号量:实际上就是一个带锁的计数器,通过锁保证同时只有一个进程访问。主要是用来作为同步手段
  • 消息队列:实际上是消息的链表,避免前面集中了传递信息量少,数据格式限制的缺点
  • 信号: 实际上是一个通知机制,该机制比较复杂,信号种类多,一个进程修改信号,其他进程根据信号变动做出相应的反应
  • 共享内存:在内存中开辟一块空间,一个进程开辟,但可以被多个进程访问,一般都是和信号量配合使用,共享内存运行效率是最快的
  • Socke:socket是唯一的一个可以在不同机器的进程的通讯,具体在网络模块说明

八. 设计模式

  1. 单例
    一个类只能实例化一个对象
    懒汉方式:不会主动实例化对象,只有在第一次调用的时候实例化,最好是在实例化的时候加锁,以避免并发的时候实例化多个对象
    饿汉方式:在程序刚开始运行的时候实例化。
  2. 工厂
  3. 消费者

九. 算法和数据算法

  1. 怎么判单链表中是否有环
    快慢指针,一个指针每次移动一个节点,另一个指针每次移动2个节点,只要这两个指针最后在某一个节点相逢,那个这个链表中接存在环结构

  2. 深度优先搜索和广度优先搜索

  3. 快排和冒泡时间复杂度

  4. 二分法

十. 网络

  1. Socket
  2. tcp/udp
  3. 三次握手,四次挥手, time_wait 为什么等待
  4. http
  5. http 和 https
  6. cookies 和 session
  7. session 表结构设计
  8. OSI七层模型
  9. DNS
  10. 网页访问的流程

interview_summary's People

Contributors

wujiniao-pro avatar

Forkers

wujiniao-pro

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.