菜单
个人主页
(当前)
写文章
浏览博文
    
搜索
登录
微信公众号
站点链接
半根蓝白个人主页
CSDN
Github
友情链接
摘繁华个人博客
博文目录
#custom-toc-container
2020-12月-面试集锦
BGLB0324
2021年1月7日 01:43
最后发布:2021年1月7日 01:43
首发:2020年12月14日 23:59
489
1
博文分类:
面试集锦
博文标签:
面试集锦
版权声明:本文为博主[BGLB0324]原创文章,遵循
CC 4.0 BY
版权协议,转载请附上原文出处链接和本声明。
本文链接:
http://blog.bglb.work/blog/blog-detail/47
版权
# 面试集锦 ## mysql存储引擎有几种?默认的存储引擎是什么?如何查看? 1. 什么是存储引擎? > 数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作。**简而言之,存储引擎就是指表的类型。数据库的存储引擎决定了表在计算机中的存储方式。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以获得特定的功能。** > 现在许多数据库管理系统都支持多种不同的存储引擎。MySQL 的核心就是存储引擎。 > MySQL 提供了多个不同的存储引擎,包括处理事务安全表的引擎和处理非事务安全表的引擎。在 MySQL 中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求,可以对每一个表使用不同的存储引擎。 2. 如何查看mysql的存储引擎呢? 终端登陆 mysql ,使用 `show ENGINES;`  **可以发现: 有很多种模式, 在mysql-5.5版本之前默认引擎是MyISAM,之后是innoDB。** 3. 不同的存储引擎有那些不同呢? - ARCHIVE Archive是归档的意思,在归档之后很多的高级功能就不再支持了,仅仅支持最基本的插入和查询两种功能。在MySQL 5.5版以前,Archive是不支持索引,但是在MySQL 5.5以后的版本中就开始支持索引了。Archive拥有很好的压缩机制,它使用zlib压缩库,在记录被请求时会实时压缩,所以它经常被用来当做仓库使用。 - BLACKHOLE 为黑洞引擎,写入的任何数据都会消失,一般用于记录binlog做复制的中继 - InnoDB 这是MySQL 5.5或更高版本的默认存储引擎。它提供了事务安全(ACID兼容)表,支持外键引用完整性约束。它支持提交、回滚和紧急恢复功能来保护数据。它还支持行级锁定。当在多用户环境中使用时,它的“一致非锁定读取”提高了性能。它将数据存储在集群索引中,从而减少了基于主键的查询的I/O。总得来说有以下优点: 1.更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。 2.事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎。 3.自动灾难恢复。与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。 4.外键约束。MySQL支持外键的存储引擎只有InnoDB。 5.支持自动增加列AUTO_INCREMENT属性。 一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择。 - MRG_MYISAM 这个以我的理解来说 就是分页用的,按照官方给的描述来说,就是可以对MyISAM存储引擎下表进行分页。 - MyISAM 该存储引擎管理非事务性表,提供高速存储和检索,支持全文搜索。并且它是独立于操作系统的,这说明可以轻松地将其从Windows服务器移植到Linux服务器;每当我们建立一个MyISAM引擎的表时,就会在本地磁盘上建立三个文件,文件名就是表明。例如,我建立了一个MyISAM引擎的tb_Demo表,那么就会生成以下三个文件: 1.tb_demo.frm,存储表定义; 2.tb_demo.MYD,存储数据; 3.tb_demo.MYI,存储索引。 MyISAM表无法处理事务,这就意味着有事务处理需求的表,不能使用MyISAM存储引擎。MyISAM存储引擎特别适合在以下几种情况下使用: 1.选择密集型的表。MyISAM存储引擎在筛选大量数据时非常迅速,这是它最突出的优点。 2.插入密集型的表。MyISAM的并发插入特性允许同时选择和插入数据。例如:MyISAM存储引擎很适合管理邮件或Web服务器日志数据。 - MEMORY 提供内存中的表,以前称为堆。它在RAM中处理所有数据,以便比在磁盘上存储数据更快地访问。用于快速查找引用和其他相同的数据。 使用MySQL Memory存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质便是系统内存。虽然在内存中存储表数据确实会提供很高的性能,但当mysqld守护进程崩溃时,所有的Memory数据都会丢失。获得速度的同时也带来了一些缺陷。它要求存储在Memory数据表里的数据使用的是长度不变的格式,这意味着不能使用BLOB和TEXT这样的长度可变的数据类型,VARCHAR是一种长度可变的类型,但因为它在MySQL内部当做长度固定不变的CHAR类型,所以可以使用。 一般在以下几种情况下使用Memory存储引擎: 1.目标数据较小,而且被非常频繁地访问。在内存中存放数据,所以会造成内存的使用,可以通过参数max_heap_table_size控制Memory表的大小,设置此参数,就可以限制Memory表的最大大小。 2.如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中。 3.存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。 - MERGE 将多个类似的MyISAM表分组为一个表,可以处理非事务性表。 MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表结构必须完全相同,尽管其使用不如其它引擎突出,但是在某些情况下非常有用。说白了,Merge表就是几个相同MyISAM表的聚合器;Merge表中并没有数据,对Merge类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行操作。Merge存储引擎的使用场景。 对于服务器日志这种信息,一般常用的存储策略是将数据分成很多表,每个名称与特定的时间端相关。例如:可以用12个相同的表来存储服务器日志数据,每个表用对应各个月份的名字来命名。当有必要基于所有12个日志表的数据来生成报表,这意味着需要编写并更新多表查询,以反映这些表中的信息。与其编写这些可能出现错误的查询,不如将这些表合并起来使用一条查询,之后再删除Merge表,而不影响原来的数据,删除Merge表只是删除Merge表的定义,对内部的表没有任何影响。 - csv CSV存储引擎的数据以文本方式存储在文件中 .CSV文件存储表内容 .CSM文件存储表的元数据,如表状态和数据量 .frm文件存储表结构信息 CSV不支持索引,所有列不能为null 一般作为数据交换的中间表。 ## 面向对象的封装、继承、多态(概念性问题) - 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 - 继承 继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展。通过继承创建的新类称为「子类」或「派生类」,被继承的类称为「基类」、「父类」或「超类」。 要实现继承,可以通过 继承和组合 来实现。 - 多态性 多态指的是同一个类产生的不同对象执行相同函数名产生不同结果的现象,其重点在于重写和重载。 重载(overload):指的是一个类的两个或多个函数名相同,参数列表不同的方法叫做重载,它们有三个特点(俗称两必须一可以): 1.方法名必须相同 2.参数列表必须不相同 3.返回值类型可以不相同 重写(override): 指的是继承自同一个父类的子类,可以通过`override`关键字重写父类的虚方法(virtual),也只能重写虚方法,其特点是: 1.方法名必须相同 2.参数列表必须相同 3.返回值类型必须相同 **C#中的几个类方法类型:** 虚方法:即为基类中定义的允许在派生类中重写的方法,使用virtual关键字定义。此方法可以直接调用。 抽象方法:在基类中定义的并且必须在派生类中重写的方法,使用 abstract 关键字定义。 隐藏方法:在派生类中定义的和基类中的某个方法同名的方法,使用 new 关键字定义。 **(1)隐藏方法不但可以隐藏基类中的虚方法,而且也可以隐藏基类中的非虚方法。 (2)隐藏方法中父类的实例调用父类的方法,子类的实例调用子类的方法。 (3)和上一条对比:重写方法中子类的变量调用子类重写的方法,父类的变量要看这个父类引用的是子类的实例还是本身的实例,如果引用的是父类的实例那么调用基类的方法,如果引用的是派生类的实例则调用派生类的方法。** ## CSharp的Linq表达式、Lambda表达式? - Lambda 是实例化委托的一个参数,也就是一个方法 - Linq 基于委托(lambda)的封装,代码重用,逻辑解耦,是一个帮助类库,linq是用泛型,委托,lamda实现的 **方法示例**: ```c# // Lambda var stu_male = Student.Where(e=>e.sex = male) ``` ```c# // Linq var stuQuery = from stu in Student Where stu.sex = male select stu; ``` ## CSharp的可空类型 C#提供了一个特殊的数据类型,可空类型,可以在其中指定正常范围值,以及空(空)值。 例如: 正常来说,`int` 类型默认值为0 那如果你想给int 赋值一个null 程序就会报错,这在数据库查询中经常会遇到。 但是 如果你定义`int`类型时 加一个`?` 程序就不会报错。像这样 ```c# int? a = null; ``` ## Django的数据表关系(多对多,一对多,一对一) 一对一: 一对多 + 唯一索引 ```python oto = models.OneToOneField( to = '主表名', # 可不加to to_field = '主表字段名', # 默认为主表的主键 on_delete = '级联方式', ) ``` 一对多:外键 ```python fk = models.ForeignKey( # django默认创建为 fk_id to='主表名', # 可不加to to_field='主表字段名', # 默认为主表的主键 on_delete='级联方式', # models.CASCADE // 父表删除,子表对应删除 # models.SET_NULL // 父表删除,子表对应置空,前提是允许置空(默认不允许置空) # models.SET_DEFAULT // 父表删除,子表对应置为默认值,前提是有默认值(default) # models.PROTECT // 子表有数据,父表不允许删除,否则报错 related_name='反向操作的manager' # 用于代替反向操作的manager, obj.child_set db_constraint = True # 是否创建约束 ) ``` 多对多: 两个一对多 1.自动创建: 可用manager修改数据 ```python mtm = models.ManyToManyField( to = '主表名', related_name= '反向操作的manager', db_constraint = True, # 是否对第三张表创建约束 db_table = None, # 第三张表名 ) ``` 2.手动创建: 手动修改数据 ```python # 1. 自定义第三表 class Table_name(models.Model): u = models.ForeignKey(Table_1) t = models.ForeignKey(Table_2) # 2. 创建关系 mtm = models.ManyToManyField( to = '主表名', related_name = '反向操作的manager', through = '自定义的第三张表', # 用于指定关系表 through_fields= ['u','t'] # 用于指定关系表中那些字段做多对多关系表 ) ``` 3.自关联: ```python+ # 1.多对多: class User: d = models.ManyToManyField('self',related_name='b') # 用户互粉 # 2. 一对多: d = models.ForeignKey(User,related_name='b') # 评论楼 ``` **2021-01-06更** ## Python与其他语言的区别你知道多少? 啊 这?有啥区别,CSharp是`public` Python是`def`? CSharp 可以重写和重载 ?(其实Python也可以)都是面向对象的 谁还不能重写和重载了! 查了百度才知道,原来是这个语言的概念性问题,直接去世…… (这答案明明知道,不知道怎么说,害,表达真的很重要尤其在面试中) **python:** Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。 什么是解释型语言:- (表达能力不好,抄点百度的官方解释) > 相对于编译型语言存在的,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。比如Python/JavaScript / Perl /Shell等都是解释型语言。 解释型语言:程序不需要编译,程序在运行时才翻译成机器语言,每执 行一次都要翻译一次。因此效率比较低。比如Basic语言,专门有一个解释器能够直接执行Basic程 序,每个语句都是执行的时候才翻译。(在运行程序的时候才翻译,专门有一个解释器去进行翻译,每个语句都是执行的时候才翻译。效率比较低,依赖解释器,跨 平台性好.) **C语言** C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。 >C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。 **C++** C++是由C语言发展而来的,与C兼容。用C语言写的程序基本上可以不加修改地用于C++。 >从C++的名字可以看出它是C的超集。C++既可用于面向过程的程序设计,又可用于面向对象的程序设计,是一种功能强大的混合型程序设计语言。(C++ 支持四种编程方法- 面向对象编程 面向过程编程 面向Lambda 模板编程 最后两个是C++ 的特性) 备注:C++不是纯面向对象语言。 **CSharp** CSharp 也叫做C# 是一个简单的、现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的。 > C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言、运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言。并定于在微软职业开发者论坛(PDC)上登台亮相。C#是微软公司研究员Anders Hejlsberg的最新成果。C#看起来与Java有着惊人的相似;它包括了诸如单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。但是C#与Java有着明显的不同,它借鉴了Delphi的一个特点,与COM(组件对象模型)是直接集成的,而且它是微软公司 .NET windows网络框架的主角。 > C#是由C和C++衍生出来的一种安全的、稳定的、简单的、优雅的面向对象编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏以及不允许多重继承)。C#综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。 > C#是面向对象的编程语言。它使得程序员可以快速地编写各种基于MICROSOFT .NET平台的应用程序,MICROSOFT .NET提供了一系列的工具和服务来最大程度地开发利用计算与通讯领域。 C#使得C++程序员可以高效的开发程序,且因可调用由 C/C++ 编写的本机原生函数,而绝不损失C/C++原有的强大的功能。因为这种继承关系,C#与C/C++具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。 **Java** Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。 > Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等 ## Python爬虫的反爬手段以及解决方案 ### 反爬虫领域常见的一些概念 因为反爬虫暂时是个较新的领域,因此有些定义要自己下: 爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量。 反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量。 误伤:在反爬虫的过程中,错误的将普通用户识别为爬虫。误伤率高的反爬虫策略,效果再好也不能用。 拦截:成功地阻止爬虫访问。这里会有拦截率的概念。通常来说,拦截率越高的反爬虫策略,误伤的可能性就越高。因此需要做个权衡。 资源:机器成本与人力成本的总和。 这里要切记,人力成本也是资源,而且比机器更重要。因为,根据摩尔定律,机器越来越便宜。而根据IT行业的发展趋势,程序员工资越来越贵。因此,通常服务器反爬就是让爬虫工程师加班才是王道,机器成本并不是特别值钱。 ### 反爬的三个方向 - 基于身份识别进行反爬 - 基于爬虫行为进行反爬 - 基于数据加密进行反爬 ### 常见基于身份识别进行反爬 1 通过headers字段来反爬 headers中有很多字段,这些字段都有可能会被对方服务器拿过来进行判断是否为爬虫 - 通过headers中的User-Agent字段来反爬: > 反爬原理:爬虫默认情况下没有User-Agent,而是使用模块默认设置 解决方法:请求之前添加User-Agent即可;更好的方式是使用User-Agent池来解决(收集一堆User-Agent的方式,或者是随机生成User-Agent) - 通过referer字段或者是其他字段来反爬 > 反爬原理:爬虫默认情况下不会带上referer字段,服务器端通过判断请求发起的源头,以此判断请求是否合法 解决方法:添加referer字段 - 通过cookie来反爬 > 反爬原因:通过检查cookies来查看发起请求的用户是否具备相应权限,以此来进行反爬 解决方案:进行模拟登陆,成功获取cookies之后在进行数据爬取 2 通过请求参数来反爬 请求参数的获取方法有很多,向服务器发送请求,很多时候需要携带请求参数,通常服务器端可以通过检查请求参数是否正确来判断是否为爬虫 - 通过从html静态文件中获取请求数据(github登录数据) > 反爬原因:通过增加获取请求参数的难度进行反爬 解决方案:仔细分析抓包得到的每一个包,搞清楚请求之间的联系 - 通过发送请求获取请求数据 >反爬原因:通过增加获取请求参数的难度进行反爬 解决方案:仔细分析抓包得到的每一个包,搞清楚请求之间的联系,搞清楚请求参数的来源 - 通过js生成请求参数 > 反爬原理:js生成了请求参数 解决方法:分析js,观察加密的实现过程,通过js2py获取js的执行结果,或者使用selenium来实现 - 通过验证码来反爬 > 反爬原理:对方服务器通过弹出验证码强制验证用户浏览行为 解决方法:打码平台或者是机器学习的方法识别验证码,其中打码平台廉价易用,更值得推荐 ### 常见基于爬虫行为进行反爬 1 基于请求频率或总请求数量 爬虫的行为与普通用户有着明显的区别,爬虫的请求频率与请求次数要远高于普通用户 - 通过请求ip/账号单位时间内总请求数量进行反爬 >反爬原理:正常浏览器请求网站,速度不会太快,同一个ip/账号大量请求了对方服务器,有更大的可能性会被识别为爬虫 解决方法:对应的通过购买高质量的ip的方式能够解决问题/购买个多账号 - 通过同一ip/账号请求之间的间隔进行反爬 > 反爬原理:正常人操作浏览器浏览网站,请求之间的时间间隔是随机的,而爬虫前后两个请求之间时间间隔通常比较固定同时时间间隔较短,因此可以用来做反爬 解决方法:请求之间进行随机等待,模拟真实用户操作,在添加时间间隔后,为了能够高速获取数据,尽量使用代理池,如果是账号,则将账号请求之间设置随机休眠 - 通过对请求ip/账号每天请求次数设置阈值进行反爬 > 反爬原理:正常的浏览行为,其一天的请求次数是有限的,通常超过某一个值,服务器就会拒绝响应 解决方法:对应的通过购买高质量的ip的方法/多账号,同时设置请求间随机休眠 2 根据爬取行为进行反爬,通常在爬取步骤上做分析 - 通过js实现跳转来反爬 > 反爬原理:js实现页面跳转,无法在源码中获取下一页url 解决方法: 多次抓包获取条状url,分析规律 - 通过蜜罐(陷阱)获取爬虫ip(或者代理ip),进行反爬 > 反爬原理:在爬虫获取链接进行请求的过程中,爬虫会根据正则,xpath,css等方式进行后续链接的提取,此时服务器端可以设置一个陷阱url,会被提取规则获取,但是正常用户无法获取,这样就能有效的区分爬虫和正常用户 解决方法: 完成爬虫的编写之后,使用代理批量爬取测试/仔细分析响应内容结构,找出页面中存在的陷阱 - 通过假数据反爬 > 反爬原理:向返回的响应中添加假数据污染数据库,通常家属剧不会被正常用户看到 解决方法: 长期运行,核对数据库中数据同实际页面中数据对应情况,如果存在问题/仔细分析响应内容 - 阻塞任务队列 > 反爬原理:通过生成大量垃圾url,从而阻塞任务队列,降低爬虫的实际工作效率 解决方法: 观察运行过程中请求响应状态/仔细分析源码获取垃圾url生成规则,对URL进行过滤 - 阻塞网络IO > 反爬原理:发送请求获取响应的过程实际上就是下载的过程,在任务队列中混入一个大文件的url,当爬虫在进行该请求时将会占用网络io,如果是有多线程则会占用线程 解决方法: 观察爬虫运行状态/多线程对请求线程计时/发送请求钱 - 运维平台综合审计 > 反爬原理:通过运维平台进行综合管理,通常采用复合型反爬虫策略,多种手段同时使用 解决方法: 仔细观察分析,长期运行测试目标网站,检查数据采集速度,多方面处理 ### 常见基于数据加密进行反爬 1 对响应中含有的数据进行特殊化处理 通常的特殊化处理主要指的就是css数据偏移/自定义字体/数据加密/数据图片/特殊编码格式等 - 通过自定义字体来反爬 > 反爬思路 : 使用自有字体文件 解决思路:切换到手机版/解析字体文件进行翻译 - 通过css来反爬 > 反爬思路:源码数据不为真正数据,需要通过css位移才能产生真正数据 解决思路:计算css的偏移 - 通过js动态生成数据进行反爬 > 反爬原理:通过js动态生成 解决思路:解析关键js,获得数据生成流程,模拟生成数据 - 通过编码格式进行反爬 > 反爬原理 : 不适用默认编码格式,在获取响应之后通常爬虫使用utf-8格式进行解码,此时解码结果将会是乱码或者报错 解决思路:根据源码进行多格式解码,或者真正的解码格式
点赞
1
打赏
暂时没有评论
请
登录
后评论
暂时没有评论