PHP 面试题
一、PHP 新版本特性
PHP 7是一个重大版本,引入了许多新特性和性能优化,比如返回类型声明、泛型、异步函数、NUllable类型和标量类型声明等。
PHP 8 (2018 - 今)
PHP 8 引入了许多新特性和改进,在性能上有大幅提升,包括Just-in-Time (JIT) 编译器、属性的初始化简化语法、Union Types(联合类型)等
二、http 状态码
HTTP协议中几个状态码的含义:1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码。
100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。
2xx (成功)
表示成功处理了请求的状态代码
200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
201 (已创建) 请求成功并且服务器创建了新的资源。
202 (已接受) 服务器已接受请求,但尚未处理。
203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
206 (部分内容) 服务器成功处理了部分 GET 请求。
3xx (重定向)
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4xx(请求错误)
这些状态代码表示请求可能出错,妨碍了服务器的处理。
400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
405 (方法禁用) 禁用请求中指定的方法。
406 (不接受) 无法使用请求的内容特性响应请求的网页。
407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408 (请求超时) 服务器等候请求时发生超时。
409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。
5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备 完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本
三、tcp三次握手和四次挥手
三次握手
TCP连接是通过三次握手来连接的。
第一次握手
当客户端向服务器发起连接请求时,客户端会发送同步序列标号SYN到服务器,在这里我们设SYN为m,等待服务器确认,这时客户端的状态为SYN_SENT。
第二次握手
当服务器收到客户端发送的SYN后,服务器要做的是确认客户端发送过来的SYN,在这里服务器发送确认包ACK,这里的ACK为m+1,意思是说“我收到了你发送的SYN了”,同时,服务器也会向客户端发送一个SYN包,这里我们设SYN为n。这时服务器的状态为SYN_RECV。
一句话,服务器端发送SYN和ACK两个包。
第三次握手
客户端收到服务器发送的SYN和ACK包后,需向服务器发送确认包ACK,“我也收到你发送的SYN了,我这就给你发个确认过去,然后我们即能合体了”,这里的ACK为n+1,发送完毕后,客户端和服务器的状态为ESTABLISH,即TCP连接成功。
在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。
四次挥手
当A端和B端要断开连接时,需要四次握手,这里称为四次挥手。
断开连接请求可以由客户端发出,也可以由服务器端发出,在这里我们称A端向B端请求断开连接。
第一次挥手
A端向B端请求断开连接时会向B端发送一个带有FIN标记的报文段,这里的FIN是FINish的意思。
第二次挥手
B端收到A发送的FIN后,B端现在可能现在还有数据没有传完,所以B端并不会马上向A端发送FIN,而是先发送一个确认序号ACK,意思是说“你发的断开连接请求我收到了,但是我现在还有数据没有发完,请稍等一下呗”。
第三次挥手
当B端的事情忙完了,那么此时B端就可以断开连接了,此时B端向A端发送FIN序号,意思是这次可以断开连接了。
第四次挥手
A端收到B端发送的FIN后,会向B端发送确认ACK,然后经过两个MSL时长后断开连接。
MSL是Maximum Segment Lifetime,最大报文段生存时间,2个MSL是报文段发送和接收的最长时间。
四、laravel 问题
1、laravel的生命周期
1、从public\index.php,进入框架;
2、注册加载composer自动生成的class loader,初始化第三方依赖;
3、生成容器(bootstrap/app.php),注册核心组件(Kernel::class);
4、处理请求,生成并返回响应;
5、结束请求,进行回调
2、yii和laravel 和thinkPHP 的区别?
yii和laravel 和thinkPHP 的优缺点
Yii、Laravel和ThinkPHP都是流行的PHP框架,每个都有其特点和适用场景。
Yii:
优点:性能出色,生产环境优化良好,功能丰富,社区活跃,有丰富的扩展。
缺点:学习曲线陡峭,对PHP新特性支持不够灵活。
Laravel:
优点:简洁的语法,支持PHP新特性,强大的功能如Eloquent ORM和依赖注入,社区生态丰富。
缺点:性能调优可能不如Yii高效,对PHP版本更新较为保守。
ThinkPHP:
优点:入门简单,有清晰的文档和教程,适合快速开发,易于学习和使用。
缺点:功能不如Yii和Laravel全面,社区活跃度不及前两者,可能缺乏某些高级特性。
五、MySQL 相关
1、视图(View)的是什么? 优点是?
MySQL视图是一种虚拟存在的表,它由一个SQL查询定义,并不存储实际的数据。 视图的定义保存在数据字典内,而创建视图所基于的表称为“基表”。视图的数据来自于查询执行的结果,并且可以像表一样被查询、更新和删除
视图可以简化复杂的SQL查询,保护数据(通过限制对特定数据的访问),更改数据格式和表示等。
2、存储过程(Stored Procedure)是什么?
存储过程是一组为了完成特定功能的SQL语句,存储在数据库中,可以通过指定的名称和参数进行调用。存储过程可以提高SQL代码的重用性,减少网络通信量,提高性能。
3、归一化是什么?它有哪些类型?
归一化是数据库设计中的一个过程,目的是减少数据冗余和提高数据完整性。常见的归一化形式包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和博耶-科得范式(BCNF)。
MySQL的三大范式是数据库设计的基本原则,它们分别是:
第一范式(1NF):
确保数据库表字段的原子性。
第二范式(2NF):
首先要满足第一范式,另外包含两部分内容,一是表必须有一个主键;二是非主键列必须完全依赖于主键,而不能只依赖于主键的一部分
第三范式(3NF):
首先要满足第二范式,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。
4、外键(Foreign Key)是什么?
外键是一种数据库约束,用于建立两个表之间的关系。在一个表中的外键会指向另一个表的主键,主要作用是维护跨表的数据完整性,确保参照完整性。
5、事务隔离级别是什么?它们如何影响并发?
https://blog.csdn.net/m0_48904153/article/details/126630012
MySQL支持四种事务隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。这些隔离级别逐渐增强了事务之间的隔离,防止了不同程度的并发问题,但同时可能降低并发性能。
5.1 事务的特性?
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部执行,要么全部不执行。这保证了事务的完整性,即事务的每一步操作要么全部成功,要么全部失败回滚
一致性(Consistency):一致性确保事务前后数据的状态转换是一个合法状态。这意味着事务执行前后的数据必须满足业务规则和约束条件,保持数据的一致性和正确性。
隔离性(Isolation):隔离性保证了多个并发事务的执行是相互隔离的。这防止了一个事务在执行过程中被其他事务干扰,从而保持了数据的隔离和独立性。隔离级别包括读未提交、读提交、可重复读和串行化,可以根据具体应用场景选择合适的隔离级别。
持久性(Durability):持久性意味着一旦事务被提交,它对数据库中数据的修改就是永久性的。即使系统发生故障,已提交的事务修改仍然保持不变。这是通过事务日志(redo log 和 undo log)来保证的,确保在系统故障后能够恢复数据
脏读 事务B读取事务A 修改但未提交的数据
不可重复读 事务A多次读取一条数据,这时事务B修改了这条数据,导致事务A 多次读取的数据不一致
幻读 当数据管理员A 在批量修改增加或者修改数据的时候,此时数据管理员在此时插入或者删除了一条数据,当数据管理员A修改完数据发现还有一条数据
没有修改到,就像发生了幻觉一样。
读未提交 产生脏读、不可重复读、幻读
读已提交 产生不可重复读、幻读 解决脏读
可重复读 产生幻读 解决脏读、不可重复读
串行化 执行效率慢,资源消耗大 解决幻读
6、如何在MySQL中使用索引优化查询?
使用索引优化查询的一种方式是确保WHERE子句中的条件使用了索引。例如,如果有一个名为students的表,其中包含name和age列,对age列有索引,那么查询SELECT * FROM students WHERE age > 18;将利用age列的索引,提高查询效率。
7、慢查询日志是什么?如何使用它来优化性能?
慢查询日志记录执行时间超过设定阈值的SQL语句,通过分析这些日志,可以找出需要优化的查询语句。开启数据库的慢查询记录功能后,可以从慢查询日志中获取哪些SQL语句执行缓慢,进而进行分析和优化。
查询五子句
where having group by limit order by
7.9. 索引有什么分类?
1、主键索引:名为primary的唯一非空索引,不允许有空值。
2、唯一索引:索引列中的值必须是唯一的,但是允许为空值。唯一索引和主键索引的区别是:唯一索引
字段可以为null且可以存在多个null值,而主键索引字段不可以为null。唯一索引的用途:唯一标识数据
库表中的每条记录,主要是用来防止数据重复插入。创建唯一索引的SQL语句如下:
3、组合索引:在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,
索引才会被使用,使用组合索引时需遵循最左前缀原则。
4、全文索引:只能在 CHAR 、 VARCHAR 和 TEXT 类型字段上使用全文索引。
5、普通索引:普通索引是最基本的索引,它没有任何限制,值可以为空。
六、no sql 产品 redis memcache mongodb
缓存穿透:大量请求根本不存在的key(下文详解)
缓存雪崩:redis中大量key集体过期(下文详解)
缓存击穿:redis中一个热点key过期(大量用户访问该热点key,但是热点key过期)
穿透解决方案:
对空值进行缓存
设置白名单
使用布隆过滤器
网警
雪崩解决方案:
进行预先的热门词汇的设置,进行key时长的调整
实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
使用锁机制
击穿解决方案:
进行预先的热门词汇的设置,进行key时长的调整
实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
使用锁机制(只有一个线程可以进行热点数据的重构)
4. 使用场景:
Redis 适用于需要高速读写、支持多种数据结构的场景,如实时分析、排行榜、会话缓存等。
Memcache 通常用于提高动态网页的性能,减轻数据库负担,适用于简单的缓存场景。
MongoDB 适合处理大量非关系型数据,如内容管理、物联网数据存储、用户数据存储等,特别是在需要灵活的数据模型和高可扩展性的应用中。
区别
1、性能
都比较高,性能对我们来说应该都不是瓶颈
总体来讲,TPS方面redis和memcache差不多,要大于mongodb
2、操作的便利性
memcache数据结构单一
redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数
mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富
3、内存空间的大小和数据量的大小
redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)
memcache可以修改最大可用内存,采用LRU算法
mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起
4、可用性(单点问题)
对于单点问题,
redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,
所以单点问题比较复杂;不支持自动sharding,需要依赖程序设定一致hash 机制。
一种替代方案是,不用redis本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡
Memcache本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的hash或者环状的算法,解决单点故障引起的抖动问题。
mongoDB支持master-slave,replicaset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切分机制。
5、可靠性(持久化)
对于数据持久化和数据恢复,
redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响
memcache不支持,通常用在做缓存,提升性能;
MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性
6、数据一致性(事务支持)
Memcache 在并发场景下,用cas保证一致性
redis事务支持比较弱,只能保证事务中的每个操作连续执行
mongoDB不支持事务
7、数据分析
mongoDB内置了数据分析的功能(mapreduce),其他不支持
六、linux
Linux 常用命令最全总结大全【推荐收藏】_linux常用命令-CSDN博客
七、shell
100 个常用 Shell 命令使用讲解(非常详细)零基础入门到精通,收藏这一篇就够了_shell命令-CSDN博客
八、游戏业务逻辑
游戏登录支付
研发登录只要负责给 token 接口,然后一个验证token的接口
发行登录,发行客户端接入研发的客户端SDK,研发客户端SDK请求服务端token后返回给发行客户端,发行客户端拿到token,请求发行服务端进行登录验证,发行服务端拿到token,整理参数,秘钥 签名等等,然后去请求研发服务端的token验证接口,研发处理完自身登录,返回登录结果给到发行服务端,
发行服务端收到请求,处理完登录逻辑后,返回给发行客户端登录信息。
发行支付
1、用户点击下单,研发客户端捕捉到,请求研发服务端下单接口;
2、研发服务端生成一个订单信息,研发唯一订单号cp_order_id,并把唯一订单号cp_order_id返回研发客户端;
3、研发客户端拿到cp_order_id,调用FUSE客户端提供的下单方法,请求下单;
4、FUSE客户端拿到cp_order_id,请求FUSE服务端下单接口;
5、FUSE服务端生成一个订单信息,FUSE聚合唯一订单号fuse_order_id,与cp_order_id一一对应,并把唯一订单号fuse_order_id返回FUSE客户端;
6、FUSE客户端拿到fuse_order_id,调用发行渠道客户端提供的下单方法,请求下单;
7、发行渠道客户端拿到fuse_order_id,请求发行渠道服务端下单接口;
8、发行渠道服务端生成一个订单信息,发行渠道唯一订单号ch_order_id,与fuse_order_id一一对应,经过支付逻辑处理,返回一个支付链接给发行渠道客户端;
9、发行渠道客户端拿到订单的支付链接,拉起支付页面;
10、用户支付成功后,支付渠道会 带上透析参数 请求其配置的回调地址(发行渠道服务端提供的支付回调接口);
11、发行渠道服务端验证支付订单成功,带上透析参数请求FUSE聚合服务端提供的支付回调接口;
12、FUSE聚合服务端验证支付订单成功,带上透析参数请求研发服务端;
13、研发服务端收到订单支付成功回调,验证成功,配合研发客户端处理发货逻辑。
游戏归因算法
抖音投放后台,会携带一个后台生成的广告ID,和素材ID,广告点进去的时候,前端在微信授权登录接口,带上链接上的广告参数,后端在微信授权回调接口 处理广告参数,并且缓存广告参数,用于后续广告回传
游戏业务
九、你认为这些项目中比较有挑战性的技术点?
因为没有版号,微信小程序跑小游戏切壳 过包屏蔽,前端根据我的接口控制,是否展示游戏入口,这个游戏入口 前端也是根据我的接口提供给他的,
根据用户跳转的IP,以及携带的链接广告参数,屏蔽所在地区,还有进入小程序的场景值 去判断是否是 微信审核或者是机器审核,
后台有相关控制功能,能做到,不同的小程序,跑不同的游戏,也可以跑同一个游戏
十、PHP 你一般都是怎么优化的呢? 从哪几个方面?
一、代码优化
减少数据库查询:数据库查询是应用程序中最耗时的操作之一。通过减少不必要的查询和优化查询语句,可以显著提高性能。使用预处理语句和参数化查询来避免SQL注入攻击,同时减少数据库查询次数。
缓存结果:对于重复计算或查询的结果,使用缓存可以避免重复计算,提高应用程序的响应速度。使用缓存系统,如Redis或Memcached,将常用数据存储在内存中,减少对数据库的访问。
优化循环和条件语句:循环和条件语句是代码中的常见结构,但如果不正确使用,可能会导致性能问题。避免在循环中进行不必要的操作,使用适当的循环结构和算法来提高性能。
使用适当的数据结构和算法:选择适当的数据结构和算法可以显著提高代码的效率和性能。了解常见的数据结构和算法的优缺点,根据实际情况选择最合适的数据结构和算法。
二、缓存优化
使用缓存系统:缓存系统可以存储常用的数据或结果,减少对数据库或其他慢速资源的访问。使用Redis或Memcached等内存中的缓存系统可以显著提高应用程序的性能。
缓存静态内容:对于不会频繁变动的静态内容,如HTML页面、图片或文件,可以将它们缓存在CDN(内容分发网络)或本地缓存系统中,减少对服务器的请求。
缓存查询结果:对于数据库查询结果,可以将它们缓存在内存中,减少对数据库的查询次数。使用适当的缓存策略,如LRU(最近最少使用)算法来管理缓存空间。
三、数据库优化
索引优化:索引是提高数据库查询性能的关键。确保对常用查询字段进行索引,并避免过多的索引,以减少数据库的负担。使用复合索引来满足多个查询条件的需求。
查询优化:编写高效的SQL查询语句是数据库优化的关键。避免使用SELECT * 语句,只选择需要的字段。使用适当的连接方式来处理表之间的关系。
数据库配置优化:根据数据库的类型和规模,进行适当的配置优化。调整数据库的缓存大小、连接池参数等配置,以提高数据库的性能和效率。
分表分库:对于大型应用程序,使用分表分库技术可以显著提高数据库的性能和可扩展性。将表或库分散到多个节点上,实现水平扩展。
四、服务器优化
负载均衡:通过负载均衡技术,将请求分发到多个服务器上,以提高应用程序的并发处理能力和容错能力。使用负载均衡器或云服务提供商提供的负载均衡功能来实现负载均衡。
服务器配置优化:根据应用程序的需求和特点,调整服务器配置参数,如内存分配、文件描述符数量等。确保服务器资源得到合理利用,避免资源瓶颈。
使用缓存服务器:将缓存服务器与应用程序服务器分离,减轻应用程序服务器的负担。使用专门的缓存服务器来存储常用数据和静态内容,提高应用程序的性能和响应速度。
使用高效的Web服务器:选择高效的Web服务器软件,如Nginx或Apache,并根据需要进行配置优化。了解服务器的性能特点和使用最佳实践来提高服务器的性能和效率。
总结:PHP优化是一个涉及多个方面的过程,包括代码优化、缓存优化、数据库优化和服务器优化等。通过综合运用这些技巧和方法,可以显著提高PHP应用程序的性能和效率。在实际开发中,根据应用程序的具体需求和特点,选择合适的优化策略并进行针对性的调整和改进。
十一、你们一般测试功能怎么测试
先本地环境自测一遍,然后放到测试环境跑,如果测试OK,在更新同步代码
单元测试、集成测试、系统测试
十二、PHP中的CI/CD技术
持续集成工具 Jenkins
十三、你平时是怎么学习新知识? 平台 方式
关注一些技术论坛, 如果有老哥发布了一些新的博客技术,会去专研
十四、jwt?
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络上安全传输信息的简洁、自包含的方式。它通常被用于身份验证和授权机制。JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
十五、进程 线程 协程
(1)进程是系统进行资源分配和调度的独立单位
(2)线程是进程的实体,是CPU调度和分配的基本单位
(3)协程,又称微线程,自带CUP上下文,是比线程更小的执行单元,占用资源小,效率高
1、进程
进程是程序一次动态执行的过程,是程序运行的基本单位。
每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。
进程占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、页表、文件句柄等)比较大,但相对比较稳定安全。协程切换和协程切换
2、线程
线程又叫做轻量级进程,是CPU调度的最小单位。
线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。
多个线程共享所属进程的资源,同时线程也拥有自己的专属资源。
线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
3、协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。
一个线程可以拥有多个协程,协程不是被操作系统内核所管理,而完全是由程序所控制。
与其让操作系统调度,不如我自己来,这就是协程
十六、vue 生命周期
Vue的生命周期是指Vue实例从创建到销毁的过程,这个过程中Vue提供了多个钩子函数,允许开发者在特定的阶段执行自定义逻辑。Vue的生命周期可以分为几个阶段,每个阶段都有其特定的用途和相关的钩子函数。以下是Vue生命周期的主要阶段和相关的钩子函数:12
初始化阶段
- beforeCreate:在实例初始化之后,数据观测和事件配置之前调用。
- created:实例已经创建完成,但DOM还未挂载。
挂载阶段
- beforeMount:模板编译完成,但尚未挂载到DOM上。
- mounted:模板已经挂载到DOM上,可以访问到DOM元素。
更新阶段
- beforeUpdate:数据更新时触发,虚拟DOM重新渲染之前调用。
- updated:虚拟DOM更新同步到DOM上后调用。
销毁阶段
- beforeDestroy:实例销毁之前调用,清理资源。
- destroyed:实例已经销毁,所有事件监听器已经被移除,DOM节点也被移除。
keep-alive 组件的生命周期
当Vue组件被<keep-alive>
包裹时,该组件的生命周期钩子函数会被调用两次:一次是正常组件创建时,另一次是组件被激活时。具体来说:
- 当组件在
<keep-alive>
内被切换时,它的activated
和deactivated
钩子函数会被调用。activated
在组件被激活时调用,通常用于恢复组件的状态;deactivated
在组件被停用时调用,用于清理资源或停止动画等。
十七、依赖注入
PHP 依赖注入(Dependency Injection, DI)是一种软件设计模式,目的是减少代码的耦合。在 PHP 中,依赖注入通常通过构造函数注入或者设置方法注入来实现
构造函数注入:通过类的构造函数接收依赖项,并将其存储在类的私有属性中。这是最常见和推荐的依赖注入方式
方法注入:依赖项通过类的方法参数传递并存储在类的属性中
属性注入:依赖项通过类的属性直接赋值
十八、技术中的难点
swoole 和redis 实现了一个异步队列操作
十九、其他语言是否有拓展
GO
二十、nginx 是否有配置过什么
https://blog.csdn.net/qq_42857358/article/details/111470750
正向代理
反向代
NGINX 负载均衡
负载均衡有三种部署方式:路由模式、桥接模式、服务直接返回模式。路由模式部署灵活,约60%的用户采用这种方式部署;桥接模式不改变现有的网络架构;服务直接返回(DSR)比较适合吞吐量大特别是内容分发的网络应用。约30%的用户采用这种模式
在NGINX中配置负载均衡通常涉及到在nginx.conf文件中的http块添加upstream块和在server块中使用proxy_pass指令
八种分配策略
轮询策略
IP_HASH
权重策略
最少链接策略
动静分离
二十一、swoole 三大模式
Swoole提供了三种运行模式:Base模式、线程模式、进程模式
1.Base模式(SWOOLE_BASE):这是一种传统的异步非阻塞Server模式,其中reactor和worker是同一个角色。在Base模式下,TCP连接是在worker进程中维持的。如果客户端连接之间不需要交互,可以使用Base模式,例如Memcache、Http服务器等。
2.线程模式:这是一种多线程Worker模式,其中Reactor线程处理网络事件轮询和读取数据,然后将请求交给Worker线程处理。然而,这种模式的缺点是当一个线程发生内存错误时,整个进程会全部结束。由于PHP的ZendVM在多线程模式下存在内存错误,多线程模式在Swoole v1.6.0版本后已关闭。
3.进程模式:与多线程Worker模式不同,进程模式使用进程代替线程。Reactor线程处理网络事件轮询和读取数据,然后将请求交给Worker进程处理。这种模式适合业务逻辑非常复杂的场景,例如WebSocket服务器等。进程模式的特点包括:
Master进程是一个多线程进程,其中有一组重要的线程称为Reactor线程(组)。每当一个客户端连接上服务器时,Master进程会从已有的Reactor线程中挑选一个专门负责向这个客户端提供维持链接、处理网络IO与收发数据等服务。
Manager进程在某种程度上可以看作是一个代理层,它不直接处理业务,而是负责将Master进程中收到的数据转交给Worker进程,或者将Worker进程中希望发给客户端的数据转交给Master进程进行发送。Manager进程还监控Worker进程,如果Worker进程因某些意外挂掉,Manager进程会重新启动新的Worker进程,实现热重载的核心机制。
Swoole通过提供这三种运行模式,使得开发者能够根据具体的应用场景和需求选择最合适的模式来构建高性能的异步服务器应用程序
二十二、PHP 和 nginx 是怎么样运行的 fpm
NGINX与PHP之间的通信主要通过两种方式进行:
FastCGI协议:这是一种通用的Web服务器与应用程序之间的通信协议。NGINX可以通过FastCGI协议与PHP解释器进行通信,发送HTTP请求并接收解释器返回的执行结果。
PHP-FPM(PHP FastCGI Process Manager):这是一个PHP FastCGI进程管理器,可以管理多个PHP解释器进程。通过与PHP-FPM进行通信,NGINX可以动态地将请求分发给不同的PHP解释器进程,实现负载均衡和高并发处理。
为了实现这一过程,需要进行一系列的配置步骤,包括安装NGINX和PHP-FPM、编辑NGINX配置文件以添加PHP解析和与PHP-FPM通信的指令等。这些配置确保了NGINX能够正确地处理PHP请求,并将结果返回给客户端。通过这种方式,NGINX和PHP可以协同工作,为Web应用程序提供高性能、高可扩展性的服务
二十三、MQ kafuka
Kafka是由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统
Kafka 的特性
高吞吐、低延迟:kakfa 最大的特点就是收发消息非常快,kafka 每秒可以处理几十万条消息,它的最低延迟只有几毫秒。
高伸缩性: 每个主题(topic) 包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中。
持久性、可靠性: Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,Kafka 底层的数据存储是基于 Zookeeper 存储的,Zookeeper 我们知道它的数据能够持久存储。
容错性: 允许集群中的节点失败,某个节点宕机,Kafka 集群能够正常工作
高并发: 支持数千个客户端同时读写
Kafka 的使用场景
活动跟踪:Kafka 可以用来跟踪用户行为,比如我们经常回去淘宝购物,你打开淘宝的那一刻,你的登陆信息,登陆次数都会作为消息传输到 Kafka ,当你浏览购物的时候,你的浏览信息,你的搜索指数,你的购物爱好都会作为一个个消息传递给 Kafka ,这样就可以生成报告,可以做智能推荐,购买喜好等。
传递消息:Kafka 另外一个基本用途是传递消息,应用程序向用户发送通知就是通过传递消息来实现的,这些应用组件可以生成消息,而不需要关心消息的格式,也不需要关心消息是如何发送的。
度量指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
日志记录:Kafka 的基本概念来源于提交日志,比如我们可以把数据库的更新发送到 Kafka 上,用来记录数据库的更新时间,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
流式处理:流式处理是有一个能够提供多种应用程序的领域。
限流削峰:Kafka 多用于互联网领域某一时刻请求特别多的情况下,可以把请求写入Kafka 中,避免直接请求后端程序导致服务崩溃
二十四、PHP数据结构
全面解读PHP-数据结构
一、常见数据结构
1、Array 数组
最简单且应用最广泛的数据结构之一
特性:使用连续的内存来存储,数组中的所有元素必须是相同的类型或类型的衍生(同质数据结构),元素可以通过下标直接访问。
2、LinkedList 链表
线性表的一种,最基本、最简单,也是最常用的数据结构。
特性:元素之间的关系是一对一的关系(除了第一个和最后一个元素,其它元素都是首位相接),顺序存储结构和链式存储结构两种存储方式。
3、double-linked-list 双向链表
特性:每个元素都是一个对象,每个对象有一个关键字key和两个指针(next和prev)。
4、Stack 栈
和队列相似,一个带有数据存储特性的数据结构。
特性:存储数据时先进后出的,栈只有一个出口,只能从栈顶部增加和移除元素。
5、Heap 堆
一般情况下,堆叫二叉堆,近似完全二叉树的数据结构。
特性:子节点的键值或者索引总是小于它的父节点,每个节点的左右子树又是一个二叉堆,根节点最大的堆叫最大堆或者大根堆,最小的叫最小堆或者小根堆。
6、list 线性表
由零个或多个数据元素组成的有限序列。
特性:线性表是一个序列,0个元素构成的线性表是空表,第一个元素无先驱,最后一个元素无后继,有长度,长度是元素的个数,长度有限。
7、queue 队列
特性:先进先出(FIFO),并发中使用 ,可以安全的将对象从一个任务传给另一个任务。
8、set 集合
特性:保存不重复元素。
9、map 字典
特性:关联数组,也被叫做字典或者键值对。
10、graph 图
特性:通常使用临接矩阵和临接表表示,前者易实现但是对于稀疏矩阵会浪费较多空间,后者使用链表的方式存储信息但是对于图搜索时间复杂度较高
二十五、Docker 概念
Docker 是一个基于go语言开发的开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化
docker 和虚拟机的区别,虚拟机携带操作系统,docker 不携带操作系统
docker三大核心概念:镜像 Image、容器 Container、仓库 Repository
镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。基于镜像可以创建容器,同一个镜像可以创建多个容器;
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。镜像存放在仓库中,可以从仓库中拉取。
二十六、PHP 常用设计模式
https://blog.csdn.net/sosemseo/article/details/127552220
单例模式确保一个类只有一个实例,并提供一个访问它的全局访问点。这在需要共享资源或管理全局状态的情况下特别有用。
工厂模式通过一个工厂类来创建对象,而不是直接使用new关键字。这可以在工厂类中根据需要决定实例化哪种具体类,隐藏对象的创建细节,并提供一个简单的接口来创建新对象。
抽象工厂模式是工厂模式的扩展,其中一个工厂类可以创建多种类型的相关对象。常用于创建一系列相关的产品,例如不同种类的数据库连接。
建造者模式用于创建复杂的对象,通过一系列简单的步骤来完成对象的构建。它可以隐藏构建过程的细节,使代码更加清晰和可维护。
原型模式基于原型对象创建其他对象的机制。可以使用该模式来避免创建复杂对象时的大量初始化过程。
适配器模式用于将不兼容的接口转换为兼容的接口。它可以帮助我们重用现有的代码,并满足特定接口的需求。
桥接模式将抽象部分与具体实现部分解耦。这种模式常用于系统设计,以便可以独立地改变抽象和实现。
装饰器模式允许在不修改现有对象的情况下,动态地向对象添加新功能。
观察者模式是一个对象通过提供方法允许另一个对象即观察者注册自己,使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。
这些设计模式各有其应用场景和优势,选择合适的设计模式可以提高代码的可维护性、可扩展性和重用性
二十七、PHP 自动加载是什么?
PHP自动加载机制是一种用于自动加载类文件的机制。在PHP中,每当使用一个未被加载的类时,PHP会自动触发一个自动加载函数,并传入该类的名称作为参数。自动加载函数负责根据类名称来查找并加载对应的类文件。
PHP自动加载机制可以通过spl_autoload_register()函数来注册自动加载函数,可以注册多个自动加载函数,当需要加载一个类时,PHP会按照注册的顺序依次调用这些函数,直到找到对应的类文件为止。
自动加载机制可以提高代码的可维护性和可扩展性,避免了手动引入大量的类文件,使代码更加简洁和易于管理
二十八、抽象类和接口
抽象类的使用场景:
当多个类具有相似的属性和方法时,可以将这些共同的部分提取到一个抽象类中,减少代码的重复性。
抽象类可以被继承,子类可以继承抽象类,并通过实现抽象类中的抽象方法来完成具体的功能。
接口的使用场景:
当一个类需要实现多个不相关的功能时,可以使用接口来定义这些功能的规范,一个类可以实现多个接口。
接口可以用于实现类之间的松耦合关系,通过接口定义的规范来进行交互,提高代码的灵活性和可维护性。
接口可以被多个类实现,从而实现多态性,提供更多的灵活性和扩展性。
总结来说,抽象类适用于具有相似属性和方法的类,而接口适用于实现多个不相关的功能或者需要实现多态性的场景。
区别:
定义方式:抽象类使用abstract
关键字定义,而接口使用interface
关键字定义。这意味着抽象类可以包含普通方法和抽象方法,并且可以包含构造方法,而接口只能包含抽象方法,并且不能包含构造方法。
实现方式:抽象类可以被继承,子类需要继承父类的属性和方法,并且必须实现父类中的抽象方法。接口则不能被继承,它只能被实现,实现了接口的类必须实现接口中所有的抽象方法。
访问修饰符:抽象类中的成员方法可以包含public
、protected
和private
三种访问修饰符,而接口中的成员方法只能包含public
访问修饰符。
使用场景:抽象类通常用于定义一些基础类,为派生类提供公共的基础方法和属性。它们可以包含普通方法和抽象方法,其中普通方法可以提供默认实现,而抽象方法则需要子类去实现。接口则主要用于定义一些可替换的类或行为,强调“能否”。
数据成员和构造函数:抽象类可以有数据成员和构造函数,可以实现数据的封装。接口中不可以声明成员变量(包括类静态变量),但可以声明类常量。这表明接口更注重于行为的定义,而抽象类在数据封装和行为定义上提供了更多的灵活性。
多态性:一个类可以实现多个接口,但只能继承一个抽象类。这意味着接口支持多态性,一个类可以实现多个接口,从而支持多种行为,而抽象类则主要用于继承和扩展基础类和功能。
二十九、PHP的垃圾回收机制
PHP5 和 PHP7 的垃圾回收机制原理都是利用 引用计数,PHP5.3之后版本为了处理循环的引用内存泄漏问题,在引用计数基础上,实现了一种复杂的算法,来检测内存对象中引用环的存在,以避免内存泄露。
引用计数:每个内存对象都分配一个 refcount计数器,当内存对象被变量引用时,refcount计数器+1;当变量引用撤掉后(执行unset()后),refcount计数器-1;当 refcount计数器=0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成。
内存泄露:当数组或对象使用 & 引用自己时,对数组或对象进行 unset,那么数组或对象会从符号表中删除,同时 refcount 减少1,但是数组或对象之前指向的refcount变为1而不是0,因此不能被回收,这样产生了内存泄露。
php5.3之后当数组或对象的指向计数(refcount)减少到非0,并且在符号表中没有任何符号映射该数组或对象时,才会产生垃圾周期,也就是说该结构体(struct 中的 zend_value)才会被放在垃圾缓冲区,被当做疑似垃圾看待,等到缓冲区达到临界值时,触发回收算法,对疑似垃圾的结构体进行遍历,将指向计数(refcount)减1,然后判断 refcount 是否为0,如果是的话就确认结构体为垃圾,最后进行销毁,释放内存空间
三十、MySQL 引擎原理
MySQL中的数据用各种不下同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎。
存储引擎是MySQL将数据存储在文件系统中的存储方式或者存储格式。
存储引擎是MySQL数据库中的组件,负责执行实际的数据I/O操作。
MySQL系统中,存储引擎处于文件系统之上,在数据保存到数据文件之前会传输到存储引擎,之后按照各个存储引擎的存储格式进行存储。
MySQL是一个开放源代码的关系型数据库管理系统,它的核心就是存储管理和查询处理,以下是关于MySQL的存储引擎原理的简单介绍:
-
存储引擎
MySQL的存储引擎是数据库的底层软件组件,负责数据的存储和提取。MySQL提供了多种存储引擎,如InnoDB、MyISAM、Memory等。可以通过
SHOW ENGINES;
命令查看MySQL支持的所有存储引擎。 -
InnoDB存储引擎
InnoDB是MySQL的默认存储引擎,它提供了事务安全(ACID兼容)和外键支持。InnoDB的主要特点包括:
-
支持ACID事务
-
行级锁定
-
外键约束
-
高性能恢复
-
支持热备份
-
MyISAM存储引擎
MyISAM是MySQL早期的默认存储引擎,但已经逐步被InnoDB取代。MyISAM的主要特点包括:
-
不支持事务和外键
-
表锁定
-
读写速度较快
-
存储结构
在MySQL中,数据以表的形式存储,每个表由一个
.frm
文件(表定义)、一个.MYD
文件(数据文件)和一个.MYI
文件(索引文件)组成。对于InnoDB存储引擎,数据和索引都存储在.ibd
文件中(如果是独立表空间的话)。 -
查询处理
MySQL的查询处理流程通常包括解析器、优化器、执行器等阶段。
-
解析器:检查SQL语法是否正确,生成解析树。
-
优化器:确定如何执行查询,生成执行计划。
-
执行器:执行查询,访问存储引擎的接口。
-
索引
索引是提高数据检索效率的重要数据结构。MySQL中,索引通常采用B-Tree或B+Tree结构。
-
缓存
MySQL使用缓存来提高查询效率,包括缓存表、索引、查询结果等。
-
并发控制
MySQL通过锁和MVCC(多版本并发控制)来处理并发操作,保证数据的一致性和完整性。
三十一、redis 为啥这么快
主要有以下4点原因:
- Redis 采用 ANSI C 语言编写,它和 SQLite 一样。采用 C 语言进行编写的好处是底层代码执行效率高,依赖性低,因为使用 C 语言开发的库没有太多运行时(Runtime)依赖,而且系统的兼容性好,稳定性高。
- 此外,Redis 是基于内存的数据库,我们之前讲到过,这样可以避免磁盘 I/O,因此 Redis 也被称为缓存工具。
- 但 Redis 快的原因还不止这些,它采用单进程单线程模型,这样做的好处就是避免了上下文切换和不必要的线程之间引起的资源竞争。
- 在技术上 Redis 还采用了多路 I/O 复用技术。这里的多路指的是多个 socket 网络连接,复用指的是复用同一个线程。采用多路 I/O 复用技术的好处是可以在同一个线程中处理多个 I/O 请求,尽量减少网络 I/O 的消耗,提升使用效率
- Redis为什么会这么快?-腾讯云开发者社区-腾讯云Redis 属于键值(key-value)数据库,键值数据库会使用哈希表存储键值和数据,其中 key 作为唯一的标识,而且 key 和 value 可以是任何的内容,不论是简单的对象还是复杂的对象都可以存储。键值数据库的查询性能高,易于扩展。https://cloud.tencent.com/developer/article/1705877
三十二、MySQL 为啥要用 B 加树的形式设计
1.B+树减少了IO次数,效率更高
(这里这么理解:-----就是减少了磁盘的访问次数,毕竟内存速度要比磁盘快的多)
2.B+树查询跟稳定,因为所有数据放在叶子节点
3.B+树范围查询更好,因为叶子节点指向下一个叶子结点
三十三、MySQL 如何避免临时表的产生?
使用临时表一般都意味着性能比较低,特别是使用磁盘临时表,性能更慢,因此我们在实际应用中应该尽量避免临时表的使用。 常见的避免临时表的方法有:
1)创建索引:在ORDER BY或者GROUP BY的列上创建索引;
2)分拆很长的列:一般情况下,TEXT、BLOB,大于512字节的字符串,基本上都是为了显示信息,而不会用于查询条件, 因此表设计的时候,应该将这些列独立到另外一张表
https://blog.csdn.net/u013421629/article/details/79556256
三十四、PHP7性能优化做了哪些优化
1、php7引入了一个新的zend引擎,名为zend engine 3.0;
2、php7提供了更好的内存管理,减少了内存泄漏和垃圾回收的成本;
3、php7还引入了新的语言特性,提高代码的可读性和安全性;
4、php7还改进了错误处理机制,可以捕获和处理致命错误,并不中止代码的执行;
5、php7通过改进底层库和模块之间的交互方式来提高性能
三十五、PHP的一个请求到 nginx 这个的流程原理是什么?
- 用户发起请求:用户在浏览器中输入URL或与Web应用互动,发送HTTP请求到Web服务器。
- DNS解析和建立TCP连接:Web浏览器解析域名并建立到Web服务器的TCP连接,通常使用HTTP(端口80)或HTTPS(端口443)。
- Nginx接收请求:Nginx接收到HTTP请求,然后根据请求的URL和其他信息将请求路由到适当的虚拟主机或应用程序。
- Nginx处理请求:Nginx可能会进行一些预处理,如静态文件缓存、反向代理或负载均衡,然后将请求传递给后端应用程序服务器,通常是PHP-FPM。
- PHP-FPM处理请求:PHP-FPM(FastCGI Process Manager)接收并处理PHP请求,将请求传递给PHP解释器。
- PHP解释器执行脚本:PHP解释器将PHP脚本执行为HTML或其他输出,可以包括数据库查询、文件操作、业务逻辑等。
- 生成HTTP响应:PHP脚本生成HTTP响应,包括HTTP响应头和HTTP响应体,响应头包括状态码、内容类型等。
- 响应返回到Nginx:生成的HTTP响应返回到Nginx,通常是通过FastCGI协议。
- Nginx响应过程:Nginx接收PHP生成的HTTP响应,可以进行额外的处理,如压缩响应、添加响应头或处理缓存,然后将处理过的HTTP响应发送到用户的浏览器。
- 浏览器接收响应:浏览器解析HTTP响应并呈现内容,这可能包括HTML、CSS、JavaScript、图像等。
这个流程展示了PHP请求如何通过Nginx进行处理和响应的过程,其中Nginx充当了反向代理服务器的角色,负责接收HTTP请求并进行转发,而PHP解释器则负责处理PHP代码并生成内容。两者通过HTTP协议进行通信,实现了动态网页的生成和展示
三十六、你觉得你PHP当中你的优势是什么?
三十七、你在这行的优势是什么?
三十八、redis 怎么样设置持久化存储
RDB(Redis DataBase):在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshotting。
RDB 持久化配置 (默认配置)
save 900 1 # 900秒内至少1个键被修改则触发保存
save 300 10 # 300秒内至少10个键被修改则触发保存
save 60 10000 # 60秒内至少10000个键被修改则触发保存
dbfilename dump.rdb # RDB文件名
dir ./ # RDB文件存储目录
AOF(Append Only File):保存Redis服务器所执行的所有写操作命令到文件
AOD 配置
appendonly yes # 开启AOF持久化存储
appendfilename "appendonly.aof" # AOF文件名
appendfsync everysec # 每秒同步一次至磁盘
四、Redis 持久化 —— 超详细操作演示!_redis持久化-CSDN博客
三十九、redis 和mysql 的区别?为啥 redis会比mysql快?
Redis和MySQL的主要区别在于它们的存储介质、数据操作方式、数据类型支持以及应用场景。Redis之所以比MySQL快,主要是因为Redis以内存为存储介质,而MySQL则主要依赖于磁盘存储。
1、存储介质与数据操作方式:
Redis主要将数据存储在内存中,这使得数据的读写速度非常快。在实际应用中,Redis只需要将数据一次性写入内存,之后对数据的读取及修改可以在内存中高效地执行,避免了磁盘寻道时间等硬盘操作时间带来的延迟,从而实现了高速访问、高效处理等功能。相比之下,MySQL的磁盘操作量大,在进行数据读取、修改等操作时,需要查询硬盘中的数据,然后再将其加载至内存中进行处理。由于磁盘读写的速度相对较慢,这导致MySQL的响应速度变慢,而Redis的操作则具有更快的响应时间。
2、数据类型支持:
Redis支持多种数据类型,包括字符串、哈希、列表、集合、有序集合等,并且每一种数据类型都可以进行丰富的操作。这种灵活性使得开发者可以灵活地调用Redis中的数据类型,以实现不同的业务需求,从而提高程序的处理性能。
3、应用场景:
Redis适合存放频繁使用的热点数据,因为其读写速度非常快,通常应用于排行榜、计数器、消息队列推送、好友关注、粉丝等场景。而MySQL则更适合进行复杂的查询和统计操作,因为它支持SQL查询,可以实现一些关联的查询以及统计。
4、分布式处理能力:
在分布式架构的场景下,Redis通过数据分片的方式对数据进行分布式处理,从而使多个Redis节点可以分摊数据操作,提高了系统的整体稳定性及可靠性。而MySQL通常由主从服务器双机部署来保证数据的高可用性,但随着数据量增大,主从复制的性能瓶颈以及单机并发量的限制将会变得更加明显,导致整体的响应速度降低。
综上所述,Redis之所以比MySQL快,主要是因为其将数据存储在内存中,避免了磁盘操作的延迟,并且支持多种数据类型和分布式处理能力,这些特点使得Redis在处理大量读写操作和高并发场景时表现出色。
四十、主从复制有几种模式
异步复制:
(Asynchronous replication)。MySQL的默认复制,主库在执行完客户端提交的事务后会立刻将执行结果返回给客户端,并不关心从库是否已经接收处理,这样带来的问题就是当主死掉了,此时主上提交的事务可能还没有传到从上。而强行将从提升为主就会导致新主上的数据不完整。
异步复制是一种基于偏移量的主从复制,实现的原理是:主库开启bbinlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息,然后连接主库进行验证,主库的IO线程根据从库slave的线程请求,从master.info开始记录的位置点向下开始取信息,同时把提取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句放在relay_log中,最终从库的sql线程会将relay_log里的sql语句应用到从库上,至此同步过程完成,以后一直循环此过程。
对于异步复制而言,主库将事务的Binlog事件写入到binlog文件中,此时主库会通知下dump线程发送这些新的binlog然后主库会继续处理提交操作,而此时并不保证这些日志会传输到任何一个从库的节点上。
全同步复制:
(Fully synchronous replication)。当主库执行完一个事务,所有的从库都执行了该事务才会将结果返回给客户端。这样保证了数据的安全性,但是因为需要等待所有从库执行完该事务才能返回客户端结果,所以全同步复制的性能必然会受到很大的影响。
对于全同步复制而言,当主库提交一个事务后,要求所有从库节点必须收到,执行并提交这些事务,然后主库线程才能继续做后续操作,而因此带来的问题就是主库完成一个事务的时间被大幅度拉长,性能降低。
半同步复制:
(Semi synchronous replication)。介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时也会造成一定程度的延迟,这个延迟为一个TCP/IP往返的时间。所以半同步复制需要在低延时的网络中使用。
对于半同步复制而言,是介于同步复制和异步复制之间的一种,主库需要等待至少一个从库节点收到并且刷新binlog到relay日志中,主库不需要等待所有从库给主库反馈,同时这里只是收到反馈而不死和完全执行并且提交事务的反馈,这样会节省很多的时间
四十一、redis 如何实现延时消费?(
1、Redis sorted set
在Redis中,zet作为有序集合,可以利用其有序的特性,将任务添加到zset中,将任务的到期时间作为score,利用zset的默认有序特性,获取score值最小的元素(也就是最近到期的任务),判断系统时间与该任务的到期时间大小,如果达到到期时间,就执行业务,并删除该到期任务,继续判断下一个元素,如果没有到期,就sleep一段时间(比如1秒),如果集合为空,也sleep一段时间。
通过zadd命令向队列delayqueue中添加元素,并设置score值表示元素过期的时间;向delayqueue添加三个order1、order2、order3,分别是10秒、20秒、30秒后过期。
zadd delayqueue 3 order3
消费端轮询队列delayqueue,将元素排序后取最小时间与当前时间比对,如小于当前时间代表已经过期移除key
2、Redis 过期键监听回调
Redis的key过期回调事件,也能达到延迟队列的效果,简单来说我们开启监听key是否过期的事件,一旦key过期会触发一个callback事件。
要启用notify-keyspace-events Ex,需要编辑redis.conf文件。 notify-keyspace-events Ex
Redis监听配置,注入Bean RedisMessageListenerContainer。
其次,配置redis监听器 最后,编写redis key过期监听回调方法
编写Redis过期回调监听方法,必须继承KeyExpirationEventMessageListener ,有点类似于MQ的消息监听。
四十二、redis 如何保证数据不被重复消费?
利用 redis 分布式锁机制
分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性
- 「互斥性」: 任意时刻,只有一个客户端能持有锁。
- 「锁超时释放」:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁。
- 「可重入性」:一个线程如果获取了锁之后,可以再次对其请求加锁。
- 「高性能和高可用」:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效。
- 「安全性」:锁只能被持有的客户端删除,不能被其他客户端删除
一、基于SETNX命令的简单分布式锁
SETNX命令是Redis中的一个原子操作,用于将一个键的值设置为一个字符串,但是只有在该键不存在时才能设置成功。基于SETNX命令实现的分布式锁可以通过以下步骤来实现:
- 在尝试获取锁之前,先生成一个唯一的标识符,可以用UUID等方式生成。
- 执行SETNX命令设置一个键,键的名字可以是业务相关的标识符,值可以是当前时间戳或者其他业务无关的值。如果SETNX命令返回1表示设置成功,即获取到了锁。
- 如果SETNX命令返回0表示键已经存在,即锁已被其他线程或者其他节点获取到,不能获取到锁。
- 在获取到锁之后,执行业务代码逻辑。
- 释放锁时,执行DEL命令删除锁对应的键。
这种简单分布式锁实现方法的优点是简单易懂,适用于单节点和少量节点的场景。但是它的缺点也十分明显,不支持锁的续约和解决死锁问题,容易受到竞态条件和网络分区等问题的影响。
二、基于SET命令的带过期时间的分布式锁
为了解决简单分布式锁的缺点,我们可以使用SET命令来实现带过期时间的分布式锁。基于SET命令的分布式锁可以通过以下步骤来实现:
- 在尝试获取锁之前,先生成一个唯一的标识符,可以用UUID等方式生成。
- 执行SET命令设置一个键,键的名字可以是业务相关的标识符,值可以是当前时间戳或者其他业务无关的值。同时设置一个过期时间,限定锁的有效期。
- 如果SET命令设置成功,即获取到了锁。如果SET命令未能设置成功,即锁已被其他线程或者其他节点获取到。
- 在获取到锁之后,执行业务代码逻辑。
- 在适当的时候,执行EXPIRE命令更新锁的过期时间,避免锁过期之前业务未能完成。
- 释放锁时,执行DEL命令删除锁对应的键。
基于SET命令的带过期时间的分布式锁可以解决简单分布式锁的不足,但是依然存在一些问题。由于Redis的主从复制机制和持久化机制的异步特性,当节点崩溃或者其他原因导致锁已过期但还未释放时,可能会出现锁重入的情况,造成数据不一致。此外,带过期时间的锁也无法解决网络分区等问题