phper
2021-12-21 17:07:02 4 举报
AI智能生成
php技术栈(最好照着写一遍,才能印象深刻。知识不是 看过即拥有,随着时间推移 大概率会忘记)。
作者其他创作
大纲/内容
软素质
简历
沟通
PPT
向上管理
如何快速融入团队
https://github.com/yuhaqiang123/my-love
子主题
面试技巧
为什么换工作
有什么想问我的
我的回答有什么建议
团队做的事
我如果入职 定位 & 向谁汇报
刚才问题、场景 的解决方案
我的 结果如何
(有自己的判断,审时度势的问)
(有自己的判断,审时度势的问)
健康
健康的活着
职级发展
P7
P7 P8 java架构师技能树
https://www.processon.com/view/601958907d9c0858d76c10dc?fromnew=1
P8
php高级工程师知识体系
https://www.processon.com/view/5cae9e72e4b0773d8c0a550c?fromnew=1
GO(另一个语言)
php 转go 注意事项
https://juejin.cn/post/6986448496987471885
经验不多
照着框架 && 说明 可以敲代码
linux
1.CPU负载和CPU利用率的区别是什么?
2.那如果CPU负载很高,利用率却很低该怎么办?
3.那如果负载很低,利用率却很高呢?
4.那如果CPU使用率达到100%呢?怎么排查?
5.说说常见的Linux命令吧?
ls
touch
https://mp.weixin.qq.com/s/7bSwKiPmtJbs7FtRWZZqpA
https://mp.weixin.qq.com/s/24vBHgtw5efC9V9yYqknNg
进程间通信
https://mp.weixin.qq.com/s/7bSwKiPmtJbs7FtRWZZqpA
https://mp.weixin.qq.com/s/CGqy0j5WvarN6mTmYB8vSA
Linux 面试题
https://www.processon.com/mindmap/6177e182e401fd6d2b18ea9d
nginx
php-fpm
1、php-fpm 单个 php 进程 占内存大小
2、php-fpm 三种模型
ondemand
在php-fpm启动的时候,不会给这个pool启动任何一个worker,是按需启动,当有连接过来才会启动。
优点:按流量需求创建,不浪费系统资源(在硬件如此便宜的时代,这个优点略显鸡肋)
缺点:由于php-fpm是短连接的
在大流量的系统上master进程会变得繁忙,占用系统cpu资源,不适合大流量环境的部署
static
启动采用固定大小数量的worker
dynamic
idle > pm.max_spare_servers
pm.min_spare_servers,
pm.max_spare_servers
pm.start_servers有效范围[pm.min_spare_servers,pm.max_spare_servers]
默认pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2
优点:动态扩容,不浪费系统资源,master进程设置的1秒定时器对系统的影响忽略不计;
缺点:如果所有worker都在工作,新的请求到来只能等待master在1秒定时器内再新建一个worker,这时可能最长等待1s;
php-fpm的工作模式和nginx类似
master + worker
每个worker都在accept本pool内的监听套接字(linux已不存在惊群现象)
4、进程模型
master 进程监控 端口
https://jiachuhuang.github.io/2017/07/06/PHP-FPM进程模型/
master:epoll
worker 处理请求
child :单进程单线程模型,每次只处理一个请求
可以保持 mysql reids 连接
https://blog.csdn.net/wuhuagu_wuhuaguo/article/details/78918771
https://www.cnblogs.com/shijianchuzhenzhi/p/6675203.html
这个解释更准
长链接 硬伤
https://blog.csdn.net/weixin_42510026/article/details/113475404
no no no 不一定
php在执行RSHUTDOWN的时候会释放所有处理本次请求的资源,如申请的变量。
那么理所当然的是我们打开的数据库连接句柄也会被释放,但是这只限于我们打开连接的时候使用的是短链接
BUT
打开的是长连接
处理完后php会收留在本次打开的连接
保留 句柄
达到长连接目的
https://blog.csdn.net/weixin_34187822/article/details/94704831?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.highlightwordscore&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.highlightwordscore
配合数据库的一些配置
数据库允许连接数要大于php-fpm子进程数
mysq再配置一下
wait_timeout 和interactive_timeout控制连接时长当一个连接很长时间没活动的时候mysql就关闭它
php活动时这边会重新建立新连接。这样避免时间长了mysql有一大堆不活动的连接。
一个 master 多个 worker
一个worker 一个长链接
这个可能会超越 mysql 、redis
长链接 数
需要新方案
代理
多个服务器
长链接数量会达到好几百
lnmp 架构
数据库
关系型数据库
MySQL
分库分表
唯一主键
字段优化
https://segmentfault.com/a/1190000016409178
长文本存储方案
https://www.zhihu.com/question/408729025
如果 静态文件还好
如果长文本中==》存在动态数据怎么办
前端 自己解析???
事务隔离级别
读未提交
没视图概念 都是返回最新的
读已提交
不同的read view
可重复度
用一个read view
序列化
回滚日志
没更早的read view删除
5.5之前回滚段删了文件也不会变小
索引
B+
Hash
等值查询
优化流程
预发跑sql explain
排除 缓存 sql nocache
看一下行数对不对 不对可以用analyze table t 矫正
添加索引 索引不一定是最优的 force index 强制走索引 不建议用
存在回表的情况
覆盖索引避免回表,不要*
主键索引
联合索引 不能无限建 高频场景
最左前缀原则 按照索引定义的字段顺序写sql
合理安排联合索引的顺序
5.6之后 索引下推 减少回表次数
给字符串加索引
前缀索引
倒序存储
Hash
数据库的flush的时机
redo log满了 修改checkpoint flush到磁盘
系统内存不足淘汰数据页
buffer pool
要知道磁盘的io能力 设置innodb_io_capacity 设置为磁盘的IOPS fio测试
innodb_io_capacity设置低了 会让innoDB错误估算系统能力 导致脏页累积
系统空闲的时候 找间隙刷脏页
MySQL正常关闭,会把内存脏页flush到磁盘
innodb刷盘速度
脏页比例
redolog 写盘速度
innodb_flush_neighbors 0
机械磁盘的随机io不太行 减少随机io性能大幅提升 设置为 1最好
现在都是ssd了 设置为0就够了 8.0之后默认是0
索引字段不要做函数操作,会破坏索引值的有序性,优化器会放弃走树结构
如果触发隐式转换 那也会走cast函数 会放弃走索引
字符集不同可能走不上索引
convert 也是函数所以走不上
聚集索引
非聚集索引
多扫描一次
减少回表
索引维护
页满了 页分裂 页利用率下降
数据删除 页合并
自增 只追加可以不考虑 也分页
索引长度
索引选择
普通索引
找到第一个之后 直到朋友不满足的
唯一索引
找到第一个不满足的就停止了
覆盖索引
包含主键索引值
最左前缀原则
安排字段顺序
索引空间问题
hash
5.6之后索引下推
不需要多个回表 一边遍历 一边判断
页的概念
更新
change buffer
更新操作来了 如果数据页不在内存 就缓存下来 下次来了 更新 在就直接更新
唯一索引 需要判断 所以 用不到change buffer
innodb的处理流程
记录在页内存
唯一索引 判断没冲突插入
普通索引 插入
记录不再页中
数据页读入内存 判断 插入
change buffer
数据读是随机IO 成本高
机械硬盘 change buffer 收益大 写多读少 marge
MVCC
版本链 在聚集索引中 有两个隐藏列 trx_id roll_pointer
读未提交
直接读取最新版本
序列化
加锁
Read View
读已提交
每次读取前生成一个
可重复度
第一次生成一个
锁
全局锁
全库逻辑备份
表锁
lock table read/write
MDL(metadata lock)
MySQL5.5引入 自动添加 读锁不互斥 写锁互斥
多个事务之前操作,如果查询的时候修改字段容易让线程池饱满
MySQL的information_schema 库的 innodb_trx 表 找到对应长事务 kill掉
alter table里面设定等待时间
Myisam是不支持表锁的
行锁
需要的时候才加上 并不是马上释放 等事务结束才释放 两阶段锁协议
死锁
超时时间
innodb_lock_wait_timeout
默认是50s太久 但是如果设置太短会误判 一般采用死锁监测
死锁机制 事务回滚
innodb_deadlock_detect = on
热点行
死锁消耗CPU
临时关闭
关掉死锁会出现大量重试
控制并发度
更多的机器 开启比较少的线程 消耗就少了
分治
间隙锁
读写锁
读
lock in share mode
for update
行锁
写
innodb如何加锁
Record lock: 对索引项加锁。
Gap lock:对索引项之间的‘间隙’,第一条记录前的间隙,或最后一条记录后的间隙 加锁
Next-Key:前两种的组合,对记录及前面的间隙加锁
Gap lock:对索引项之间的‘间隙’,第一条记录前的间隙,或最后一条记录后的间隙 加锁
Next-Key:前两种的组合,对记录及前面的间隙加锁
B+
log
undo log
回滚 mvcc
redo log
物理日志 内存操作记录
sync_binlog 可以优化日志写入时机
binlog
组提交机制,可以大幅度降低磁盘的IOPS消耗。
两段式提交 redo 准备 binglog 提交
count1 *
mvcc影响
主备延迟
强制走主
sleep
join
驱动表
id用完
bigint
row_id 没设置主键的时候
thread_id
mysql io性能瓶颈
设置 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count参数,减少binlog的写盘次数。这个方法是基于“额外的故意等待”来实现的,因此可能会增加语句的响应时间,但没有丢失数据的风险。
将sync_binlog 设置为大于1的值(比较常见是100~1000)。这样做的风险是,主机掉电时会丢binlog日志。
将innodb_flush_log_at_trx_commit设置为2。这样做的风险是,主机掉电的时候会丢数据。
将sync_binlog 设置为大于1的值(比较常见是100~1000)。这样做的风险是,主机掉电时会丢binlog日志。
将innodb_flush_log_at_trx_commit设置为2。这样做的风险是,主机掉电的时候会丢数据。
常见命令
show processlist
查看空闲忙碌链接
wait_timeout
客户端空闲时间
定时断开链接
mysql_reset_connection 恢复链接状态
innodb_flush_log_at_trx_commit
redolog事务持久化
sync_binlog
binlog事务持久化
真实故障
数据库挂了 show processlist 一千个查询在等待 有个超长sql kill 但是不会引起flush table 周末 优化脚本 analyze 会导致 MySQL 监测到对应的table 做了修改 必须flush close reopen 就不会释放表的占用了
Mysql==>朋
事务 Transaction
特性
A
Atomicity
原子性
C
Consistency
一致性
原子性、持久性和隔离
I
Isolation
隔离性
四种级别
读未提交
读已提交
MVCC
读取 历史版本,即修改的时候生成 新版本
可重复读
MVCC + 间隙锁(Next-key Lock)
InnoDB默认级别
为解决问题:
不可重复读可能发生在update,delete操作中,而幻读发生在insert操作中。
并不是完全解决了幻读的问题
解决:
解决了读数据情况下的幻读问题
未解决:
修改的操作下 存在幻读问题
但是有一点大家是一致的,就是RR在数据库标准定义里是没有解决幻读问题的
同一条数据,在一次事务中 读取的数据是一致的(MVCC 读取记录的历史版本数据)
RR级别下防止幻读
只要对 SELECT 操作也手动加行(X)锁即可类似 SERIALIZABLE 级别(它会对 SELECT 隐式加锁),即大家熟知的:
https://segmentfault.com/a/1190000016566788
# 这里需要用 X锁, 用 LOCK IN SHARE MODE 拿到 S锁 后我们没办法做 写操作
SELECT `id` FROM `users` WHERE `id` = 1 FOR UPDATE;
如果 id = 1 的记录存在则会被加行(X)锁,如果不存在,则会加 next-lock key / gap 锁(范围行锁),即记录存在与否,mysql 都会对记录应该对应的索引加锁,其他事务是无法再获得做操作的。
这个讲得对!!!!
MVCC + review机制 + 锁
串行化读
https://blog.csdn.net/zzti_erlie/article/details/88080822
实现原理
锁 + MVCC
如果没有 隔离 ==》出现的问题
脏读
不可重复读
侧重表达 读-读
幻读
定义???
类型
https://blog.csdn.net/zzti_erlie/article/details/88080822
则是说 读-写,用写来证实读的是鬼影。
RR级别下,Next-Key Lock才能彻底解决幻读
产生幻觉似的情况
D
Durability
持久性
redo log
Innnodb有很多 log,持久性靠的是 redo log。
WAL
https://zhuanlan.zhihu.com/p/358813168
锁
两阶段锁协议。
行锁是在需要的时候才加上 的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。
行锁
间隙锁
临键锁
表锁
共享锁
意向锁
自增锁
插入锁
参考
https://blog.csdn.net/Saintyyu/article/details/91269087
解锁呢???
事务结束 锁就自动 解除了么???
lock tables table_name read
lock tables table_name write
unlock tables
创建行锁 必须 是 事务!!!
当前读
===》 当前记录行 + 锁 && 对查询范围空间的数据 + 间隙锁(gap lock) ==> 阻止了幻读
MySQL 锁、隔离级别 、MVCC 实现三者关系
https://blog.csdn.net/marco__/article/details/95939503
四种隔离级别
事务
ACID
未提交读
读到事务未提交的数据
提交读
读到 事务提交 但是未结束的 数据
能够避免上一种 情况
可重复读
可以重复读取数据,不受其他事务(增删改)影响
本次事务内读取数据的一致性
避免了 上一种问题
存在幻读
MVCC + 锁 ===》实现
如何实现的呢
MVCC + readview
undo log 就是 版本记录 多个undolog 就是数据的版本链(历史记录)
这个过程涉及 了 锁、wal、多版本、review 等
锁的实现
乐观锁
数据版本实现
记录取数据时版本,
修改时版本+1
提交时 对比版本
悲观锁
包含
共享锁
排它锁
增删改
实现
共享锁(读锁)
可读不可写,想写须释放完
select * from table lock in share mode
排它锁
注意: 其它应该是可以读的
select * from table for update
行锁
给一行数据进行加锁
表锁
实现
当前读
快照读
record lock(记录锁)
行锁???
锁位置
在索引上!!!
gap lock(间隙锁)
在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。gap lock的机制主要是解决可重复读模式下的幻读问题。
next-key lock
在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。gap lock的机制主要是解决可重复读模式下的幻读问题。
mysql 两种事务隔离技术
mvcc
优势是不加锁,并发性高。缺点是不是实时数据
next-key
优势是获取实时数据,但是需要加锁。
幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。
key: 前后两次 范围内 筛选,不同结果
https://www.jianshu.com/p/77a1cd3187b6
序列化读
序列化操作(读、写 都是 串行化执行)
避免 上述问题
场景
数据库防止库存超卖问题:
参考:https://segmentfault.com/a/1190000012469586
UPDATE products SET quantity = '1' WHERE id=3 AND quantity > 0;
update更新语句会把并发串行化
beginTranse(开启事务)
try{
//quantity为请求减掉的库存数量
$dbca->query('update s_store set amount = amount - quantity where amount>=quantity and postID = 12345');
}catch($e Exception){
rollBack(回滚)
}
commit(提交事务)
SQL 书写
https://zhuanlan.zhihu.com/p/267339165
雇佣表的 各种sql
非关系型数据库
KV
Mongdb
redis
memecached
分库分表
中间件
原理
场景方案
锁
乐观锁、悲观锁
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzAwNDA2OTM1Ng==&action=getalbum&album_id=1761987817540206592&scene=173&from_msgid=2453150113&from_itemidx=1&count=3&nolastread=1#wechat_redirect
互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景
https://mp.weixin.qq.com/s/6QrQ0TZVqSQq26Rms0_mvA
高可用
高并发
PHP
语言
语法
New self 和 new static 的区别:
new self()和new static()的区别只有在继承中才能体现出来,如果没有任何继承,
那么这两者是没有区别的。
在继承中,new self()返回的实例是万年不变的,无论谁去调用,都返回同一个类
的实例,而new static()则是由调用者决定的。
基础
PHP
引用变量
数据类型
标量
boolean(布尔型)
integer(整型)
float(浮点型,也称double)
string(字符串型)
复合
array(数组)
实现原理 PHP7 底层实现
哈希表+双向链表实现
HashTable结构体
哈希表的基本信息
Bucket结构体
保存数据的具体内容
数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型
如何理解 有序 二字??
hash 是无序的???
arData
中间表
为了实现 HashTable 的有序性,PHP 为其增加了一张中间映射表
https://juejin.cn/post/6844903696988373005
bucket 是数组 有序的
中间表 用来存储 hashTable 索引呗 !!!!
查找过程
轻易的实现集合、栈、列表、字典等多种数据结构。
扩容
时机:
当插入一个元素且没有空闲空间时
触发自动扩容机制
判断删除是否阈值
是
移除已被逻辑删除的 Bucket
后面的bucket 向前移动 ,补足被删除的位置
注意: 因为 Bucket 的下标发生了变动,所以还需要更改每个元素在中间映射表中储存的实际下标值。
否
申请原数组两倍的 新数组
迁移 旧数据 ==》新数据
计算新的 映射关系 ===》重建索引
扩容后再执行插入
重建散列表
时机:
删除 数组元素
标志位对该元素进行逻辑删除
即在删除 value 时只是将 value 的 type 设置为 IS_UNDEF
不会立即删除该元素所在的 Bucket
- 删除元素达到一定数量 或扩容后都需要重建散列表
遍历 Bucket 数组中的 value,然后重新计算映射值更新到散列表
https://blog.csdn.net/wm31898/article/details/101511106
object(对象)
特殊
resource(资源)
NULL
PHP超级全局变量
网址
https://www.cnblogs.com/wangxin-king/p/5669336.html#:~:text=PHP%E8%B6%85%E7%BA%A7%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E3%80%81%E9%AD%94%E6%9C%AF%E5%8F%98%E9%87%8F%E5%92%8C%E9%AD%94%E6%9C%AF%E5%87%BD%E6%95%B0.%20PHP%E5%9C%A8%E8%AE%BE%E8%AE%A1%E7%9A%84%E6%97%B6%E5%80%99%E5%B7%B2%E7%BB%8F%E9%A2%84%E5%AE%9A%E4%B9%89%E4%BA%869%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E3%80%818%E4%B8%AA%E9%AD%94%E6%9C%AF%E5%8F%98%E9%87%8F%E5%92%8C13%E9%AD%94%E6%9C%AF%E5%87%BD%E6%95%B0%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%8F%98%E9%87%8F%E5%92%8C%E5%87%BD%E6%95%B0%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%84%9A%E6%9C%AC%E7%9A%84%E4%BB%BB%E4%BD%95%E5%9C%B0%E6%96%B9%E4%B8%8D%E7%94%A8%E5%A3%B0%E6%98%8E%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E3%80%82.,%E5%9C%A8PHP%E5%BC%80%E5%8F%91%E4%BC%9A%E9%A2%91%E7%B9%81%E7%9A%84%E4%BD%BF%E7%94%A8%E8%BF%99%E4%BA%9B%E5%8F%98%E9%87%8F%E5%92%8C%E5%87%BD%E6%95%B0%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%8F%98%E9%87%8F%E5%92%8C%E5%87%BD%E6%95%B0%E5%8F%AF%E4%BB%A5%E6%96%B9%E4%BE%BF%E7%9A%84%E5%B8%AE%E6%88%91%E4%BB%AC%E8%A7%A3%E5%86%B3%E5%BE%88%E5%A4%9A%E9%97%AE%E9%A2%98%E3%80%82.%20%E4%B8%8B%E9%9D%A2%E8%AF%A6%E7%BB%86%E7%9A%84%E8%AE%B2%E8%A7%A3%E4%B8%8BPHP%E4%B8%AD%E7%9A%84%E8%B6%85%E7%BA%A7%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E3%80%81%E9%AD%94%E6%9C%AF%E5%8F%98%E9%87%8F%E5%92%8C%E9%AD%94%E6%9C%AF%E5%87%BD%E6%95%B0%E3%80%82.
$GLOBALS
$_SERVER
$_REQUEST
$_POST
$_GET
$_FILES
$_ENV
$_COOKIE
$_SESSION
常量
预定义常量
PHP_OS
PHP_VERSION
TRUE
FALSE
NULL
DIRECTORY_SEPARATOR
PATH_SEPARATOR
E_ERROR
E_WARNING
E_PARSE
E_NOTICE
M_PI
... ...
魔术常量
__FILE__
__LINE__
__FUNCTION__
__CLASS__
__METHOD__
... ...
_DIR_
_NAMESPACE_
运算符
流程控制
函数的应用
echo,pint,print_r,var_dump的区别
内置函数
回调函数
匿名函数和闭包
数组
预定义数组
$_SERVER
$_ENV
$_GET
$_POST
$_REQUEST
$_FILES
$_COOKIE
$_SESSION
$GLOBALS
数组函数
array_merge与数组相“+”的区别
面向对象
三大特性
封装
类的权限修饰符
public
protect
private
继承
单一继承
方法重写
多态
抽象类 abstract
接口 interface
魔术方法
__construct
__destruct
__set
__get
__call
__callstatic
__isset
__unset
__sleep
__wakeup
__tostring
__clone
设计模式
工厂模式
单例模式
注册树模式
适配器模式
观察者模式和策略模式
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzAwNDA2OTM1Ng==&action=getalbum&album_id=1761987817540206592&scene=173&from_msgid=2453150113&from_itemidx=1&count=3&nolastread=1#wechat_redirect
对象 对比 == ===
https://www.php.net/manual/zh/language.oop5.object-comparison.php
字符串处理
相关函数
正则表达式
字符类型
行定位符
单词定界符
选择字符
排除字符
限定符
点号操作符
转义字符
预定义的字符集
括号字符
模式修饰符
应用场景
字符串匹配
字符串替换
字符串分隔
贪婪匹配与懒惰匹配
回溯与固态分组
文件处理
会话控制
COOKIE
SESSION
常用框架
Laravel
TP
CI
swoole
PHP7
PHP7与PHP5的区别
性能提升的原因
如何解决PHP内存溢出问题
垃圾回收机制
PHP的运行原理
CGI
FastCGI
PHP-FPM
常用配置项
基础数据类型
高级语法 && 数据结构 && SPL
高级语法
数据结构
双向链表
SplDoublyLinkedLIst
栈
SplStack
队列
SplQueue
堆
SplHeap
大根堆
SplMaxHeap
小根堆
SplMinHeap
优先级队列
SplPriorityQueue
固定数组
SplFixedArray
对象存储
SplSorageObject
wiki
https://blog.csdn.net/bani_love/article/details/50419753#:~:text=php%20SPL%EF%BC%88Standard%20PHP%20Library%EF%BC%89%20%E4%B8%BB%E8%A6%81%E7%94%A8%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E6%9C%89%EF%BC%9A%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8%20%28SplDoublyLinkedList%29%EF%BC%8C%E6%A0%88,%28SplStack%29%EF%BC%8C%E9%98%9F%E5%88%97%20%28SplQueue%29%EF%BC%8C%E5%A0%86%20%28SplHeap%29%EF%BC%8C%E5%A4%A7%E6%A0%B9%E5%A0%86%20%28SplMaxHeap%29%EF%BC%8C%E5%B0%8F%E6%A0%B9%E5%A0%86%20%28SplMinHeap%29%EF%BC%8C%20%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97%EF%BC%88SplPriorityQueue%EF%BC%89%EF%BC%8C%E5%9B%BA%E5%AE%9A%E6%95%B0%E7%BB%84%EF%BC%88SplFixedArray%EF%BC%89%EF%BC%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%EF%BC%88SplStorageObject%EF%BC%89%E3%80%82
SPL
1、定义
a collection of interfaces and classes that are meant to solve standard problems
使用 object 模仿 array行为 的 interface、 class
so ==>
interface
Iterator 迭代器
function
current()
key()
next()
rewind()
valid()
https://www.ruanyifeng.com/blog/2008/07/php_spl_notes.html
可以在 foreach 、while中使用
ArrayAccess
offsetExists($offset)
offsetGet($offset)
offsetSet($offset, $value)
offsetUnset($offset)
IteratorAggregate
RecursiveIterator
function
current()
key()
next()
rewind()
valid()
getChildren()
hasChildren()
https://www.ruanyifeng.com/blog/2008/07/php_spl_notes.html
可以在 foreach 、while中使用
SeekableIterator
function
current()
key()
next()
rewind()
valid()
seek()
https://www.ruanyifeng.com/blog/2008/07/php_spl_notes.html
可以在 foreach 、while中使用
class
查看所有的内置类,可以使用下面的代码
<?php
// a simple foreach() to traverse the SPL class names
foreach(spl_classes() as $key=>$value)
{
echo $key.' -> '.$value.'<br />';
}
?>
// a simple foreach() to traverse the SPL class names
foreach(spl_classes() as $key=>$value)
{
echo $key.' -> '.$value.'<br />';
}
?>
DirectoryIterator
foreach、while
实现了 哪些迭代的接口
ArrayObject
Array转化为object
ArrayIterator
对ArrayObject类的补充,为后者提供遍历功能
RecursiveArrayIterator
RecursiveIteratorIterator
FilterIterator
SimpleXMLIterator
CachingIterator
SplFileObject
相关函数
类相关函数
类的继承、接口、特性查看
class_implements()
当前类实现了哪个接口
class_parents()
查看某个类对象的父类
class_uses()
当前类对象所使用的 trait 特性信息
spl_object_hash(new TestA)
类的哈希
spl_object_id()
对象的 ID
spl_classes()
所有SPL 可使用 类
迭代器相关的函数
iterator_to_array()
iterator_to_array($iterator, true)
$iterator = new ArrayIterator(['a'=>'a1', 'b'=>'b1', 'c'=>'c1']);
var_dump(iterator_to_array($iterator, true));
// array(3) {
// ["a"]=>
// string(2) "a1"
// ["b"]=>
// string(2) "b1"
// ["c"]=>
// string(2) "c1"
// }
var_dump(iterator_to_array($iterator, true));
// array(3) {
// ["a"]=>
// string(2) "a1"
// ["b"]=>
// string(2) "b1"
// ["c"]=>
// string(2) "c1"
// }
iterator_to_array($iterator, false)
var_dump(iterator_to_array($iterator, false));
// array(3) {
// [0]=>
// string(2) "a1"
// [1]=>
// string(2) "b1"
// [2]=>
// string(2) "c1"
// }
// array(3) {
// [0]=>
// string(2) "a1"
// [1]=>
// string(2) "b1"
// [2]=>
// string(2) "c1"
// }
iterator_count($iterator)
iterator_apply()
通过一个指定的回调函数来遍历一个迭代器
array_wlack ???
自动加载相关函数
spl_autoload_register()
维护了一个自动加载方法的队列
相当于是多个 __autoload() 的功能
spl_autoload_functions()
获取 目前自动加载的 类 or 方法列表
spl_autoload_unregister
应用方向 Composer
https://zhuanlan.zhihu.com/p/426015371
深入学习Composer原理
文件加锁 解锁 ==》 代码实现
stream socket 扩展异同
curl
socket
socket更底层,类似于C语言的socket接口
Tcp
Udp
使用起来比较麻烦。
必须安装socket扩展
优点:
是可以设置很多socket选项
stream
在 socket 基础上分装的
HTTP 上下文是为 PHP 内建的标准 I/O 接口准备
PHP自带的接口,无需安装任何扩展
使用非常简单
stream_socket_server 创建的socket属于stream类型
stream相关的函数
fread
fwrite
过滤器
streamWrapper
SSL加密等
缺点:
很多socket选项无法精确设置
socket_import_stream
===》
转换成底层sockets
socket_set_option设置stream_socket的socket选项了。
答案参考wiki
http://www.blogdaren.com/post-2373.html
错误处理
PHP错误异常与处理
https://www.processon.com/view/5e5f242fe4b0f8585546e105?fromnew=1
屏蔽PHP错误
1、@
2、error_reporting(0);
3、display_errors -->php.ini
4、try catch
5、set_expetion_handler
6、set_error_handler
生命周期
执行过程
5个步骤
程序启动,Zend引擎和核心组件初始化
moudle_init
request_init
excute
执行过程
PHP 代码 => Token => 抽象语法树 (AST)=> Opcodes => 执行
request_down
module_down
程序关闭
不同类型下 上述步骤执行不同
SAPI生命周期
1、2、6、7 整个生命周期中只会执行一次
3、4、5 会在每次 request 生命周期内重复执行
CGI/CLI模式
1~7 只执行一次
https://segmentfault.com/a/1190000015453391
内存
内存分配机制
三层次
接口层
emalloc efee
给扩展封装的,封装了对系统内存的请求
堆层
通过 zendMM 与 程序员代码 交互
程序员代码 交互
三种类型表
free_bucket
large_free_bucket
rest_buckets
存储层
mmap、malloc、free
跟系统内存交互;对 堆层屏蔽 系统操作。
https://www.jianshu.com/p/63a381a7f70c
php 内存回收机制
1、引用计数 计数为 0
2、离开变量的作用域---》会被自动清除(不包含静态变量)
3、5.3 循环引用 会内存泄露, 5.3后新的算法
a、引用计数
php 5.3 以前 简单引用计数
--》 当refcount 为0 的时候就会回收垃圾。
==》归还 给 zendMM ;由其处理,归还操作系统 or 存放 bucket 、fastcache 中重复利用。
现在发现的 所有垃圾回收都是 先 标记,后回收,并不是 马上清除,可能是考虑性能吧,可能会定时吧
5.3 之后引入复杂的算法,解决 循环引用导致内存泄露问题。
同步算法 --》还是基于引用计数法
(https://blog.csdn.net/ty_hf/article/details/52906258)
zval 相关两个属性:isref refcount
新算法: 三个准则:
1、 refcount 在增长 不处理,说明在使用
2、refcount 减少0 -》释放,
3、减少不为0 -》不释放,可能为垃圾 ==>需要判断
分析第3种情况: 第3种情况的zval 放入(应该是减完之后的zval)一个节点( root)缓存区(root buffer)&& 标记紫色 && 且 在 缓存区只出现一次。==》缓存区满(10000个)--》GC判断 ==》 缓存区啥数据结构 ==》 双向链表
==》 GC 操作: 对 每一个zval 进行深度遍历(每个zval 本身可能是链表、树啊)&& (zval 节点中包含的zval 都减1 ) && 标记灰色
==> 再次 以 深度优先 判断节点中zval 中refcount 值 ==》a(if 0 && 标记白色)b (if !0 recount +1 ??? (对非垃圾还原) && 黑色)
===》 遍历 zval 节点,将上一步,标记白色的zval 释放掉。
==》 GC 操作: 对 每一个zval 进行深度遍历(每个zval 本身可能是链表、树啊)&& (zval 节点中包含的zval 都减1 ) && 标记灰色
==> 再次 以 深度优先 判断节点中zval 中refcount 值 ==》a(if 0 && 标记白色)b (if !0 recount +1 ??? (对非垃圾还原) && 黑色)
===》 遍历 zval 节点,将上一步,标记白色的zval 释放掉。
历史角度 看 php gc 发展过程
(http://niliu.me/articles/1261.html)
(- ~5.3) [5.3 ~7.0) [7.0 ~
GC
进程&线程模型
线程安全
https://mp.weixin.qq.com/s/6QrQ0TZVqSQq26Rms0_mvA
TSRM??? 没看懂的
这块什么鬼???
这块什么鬼???
线程安全资源管理器(Thread Safe Resource Manager)
PHP 源码的 /TSRM 目录下,调用随处可见,通常,我们称之为 TSRM 层
只会在被指明需要的时候才会在编译时启用(比如,Apache2+worker MPM,一个基于线程的MPM)
Win32 下的 Apache 来说,是基于多线程的,所以这个层在 Win32 下总是被开启的。
线程之间共享的存在于进程的内存空间的全局变量
tsrm_tls_entry
tsrm_resource_type
https://segmentfault.com/a/1190000010004035
https://www.zhihu.com/question/36734873
非线程安全版存在的意义就是Linux里很少用多线程模型所以不需要线程安全。
编译
php新特性
7
https://www.processon.com/view/5d08852ee4b0376de9bc407d?fromnew=1
PHP 7底层设计与源码实现
https://www.processon.com/view/5e5b78c6e4b03627650b89df?fromnew=1
8
框架
Yii
Laravel
https://www.processon.com/view/5f98cd96e401fd6f36652370?fromnew=1
https://www.processon.com/view/5876fa44e4b0de31f00c970f?fromnew=1
https://www.processon.com/view/5733e032e4b0c102ad204779?fromnew=1
laravel 生命周期
https://www.processon.com/view/5b29c5c8e4b06df80ab46eaf?fromnew=1
DB
https://www.processon.com/view/57ad3864e4b0f39769da5b45?fromnew=1
框架
https://www.processon.com/view/58640aa6e4b049e79ed0fb74?fromnew=1
https://www.processon.com/view/5878a85ee4b0de31f0260e66?fromnew=1
https://www.processon.com/view/56736b09e4b0b315aefb62d4?fromnew=1
Facdes
框架特性
IOC
https://mp.weixin.qq.com/s/WpRSitDqtgOuU9GnI1-HDw
AOP
https://mp.weixin.qq.com/s/NXZp8a3n-ssnC6Y1Hy9lzw
事务传播
https://mp.weixin.qq.com/s/IglQITCkmx7Lpz60QOW7HA
常驻内存类型框架
swoole
workerman
写一个框架注意的点
MVC
composer
github & packagist
annotation
di
Route
扩展
phpinfo();
get_loaded_extensions()
extension_loaded("redis");
php -m
PHP配置文件php.ini
extension=要开启的扩展名称
安装
框架
yaf
phalcon
Swoole
包管理
composer
php 并发编程
并发编程总结
https://github.com/yuhaqiang123/my-love
API设计
正则表达式
php 安全
设计模式
设计模式
工厂模式
单例模式
注册树模式
适配器模式
观察者模式和策略模式
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzAwNDA2OTM1Ng==&action=getalbum&album_id=1761987817540206592&scene=173&from_msgid=2453150113&from_itemidx=1&count=3&nolastread=1#wechat_redirect
单例
工厂
简单工厂
抽象工厂
建造者模式
适配器模式
桥接模式
代理模式
装饰器模式
策略模式
观察者模式
责任链模式
命令行模式
子主题
网络
web socket
网络协议
物理层
基于 0 1 0 1 的传输
机械、电气、功能与规程的特性
链路层 data link layer
基于mac 的 帧
每个设备一个 UUID
ISO1745--1975
IP
ICMP
ARP 、RARP
传输层
TCP
三次握手、四次挥手
UDP
应用层
FTP
DNS
Telent
SMTP
NFS
SNMP
HTTP
HTTP1
CODE码
1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求
状态码、1XX,2XX 3XX 4XX 5XX
方法 get post delete
http的keep-alive 作用: 保持tcp 连接 防止, http、tcp 连接断开
HTTPS
HTTP2
HTTP3
https://mp.weixin.qq.com/s/AK1Pb9rx0q5Hf8dq6HNOhw
http https 异同
本质
地址 + 封包
网关
nginx
LVS
MQ
RocketMQ
基础组成
NameServer
无状态模式
broker向发心跳顺便带上所有的Topic信息
早期是zk后来改了
Broker
中转消息,消息持久化
底层通信基于Netty
Producer
同步
异步
单向
Consumer
pull
push
支持集群模式
多master
多master多slave异步复制
多master多slave双写
消费保证
发送成功后返回consume_success
回溯消费
高可用
集群
NameService 集群
Broker 主从 双主 双从
Consumer 自动切换
producer 链接两个Broker
刷盘
同步 超时会返回错误
异步 不返回
消息的主从复制
同步复制
异步复制
主从同步 异步刷盘
顺序消息
Hash取模
RocketMQ提供了MessageQueueSelector队列选择机制
顺序发送 顺序消费由 消费者保证
消费者是多线程
消息去重
幂等
去重
消息表主键冲突
分布式事务
最大努力
消息表 不断轮训 人工干预
半消息
发送半消息 发送成功 本地事务 觉得是否提交还是回滚 服务端没收到回查 检查本地事务 根据本地事务决定 提交
2/3pc
最终一致
预发 持久化 返回状态 发送处理结果 判断是否干掉持久化的 发送
完整的一个调用链路
producer 和NameService 节点建立一个长连接
定期从NameService获取Topic信息
并且向Broker Master 建立链接 发送心跳
发送消息给 Broker Master
consumer 从 Mater 和 Slave 一起订阅消息
消息重试
顺序消息重试
不断重试 16次 4小时46分钟 可以修改尝试次数
对一个消费者设置 组内都会设置
可以获取消息重试次数
无序消息重试
死信队列
不再被正常消费
保存3天
面向消费者组
控制台 重发 重写消费者 单独消费
事务消息
消息丢失
消息积压
决定是否丢弃
判断吞吐量
停止消费 加机器 加topic
MQ 选择对比
https://zhuanlan.zhihu.com/p/70123414
https://note.dolyw.com/mq/00-MQ-Select.html#_6-对比
https://blog.csdn.net/wqc19920906/article/details/82193316
RabbitMQ
https://developer.aliyun.com/article/769883
必知必会 RabbitMQ面试题 33道
https://cloud.tencent.com/developer/article/1816305
底层原理
https://www.processon.com/view/5fc0a588e0b34d3ef4953912?fromnew=1
广播
https://blog.csdn.net/fakerswe/article/details/81455340
就是把交换机(Exchange)里的消息发送给所有绑定该交换机的队列,忽略routingKey
RabbitMQ消息模型的核心思想(core idea): 生产者会把消息发送给RabbitMQ的交换中心(Exchange),Exchange的一侧是生产者,另一侧则是一个或多个队列,由Exchange决定一条消息的生命周期–发送给某些队列,或者直接丢弃掉。
RabbitMQ使用教程(超详细)
https://blog.csdn.net/lzx1991610/article/details/102970854
延迟队列
基于kafka 设计的
RabbitMQ延时队列
https://zhuanlan.zhihu.com/p/75710822
6种 延时队列的实现方案
https://juejin.cn/post/6844904150703013901
RPC
分布式
两阶段
三提交TCC
Zookeeper
选举机制
过半机制
预提交 ack 2pc
ZAB协议?
zk节点宕机如何处理?
如何实现分布式一致性
https://mp.weixin.qq.com/s/gphDLJMO3QcRoN3zkco4EA
https://github.com/AobingJava/JavaFamily
分布式锁
Zookeeper
死锁
羊群效应
临时节点顺序
性能没redis高
Redis
jedis.set(String key, String value, String nxxx, String expx, int time)
性能比较高
数据库
死锁
设置一个失效时间用定时任务去跑
数据库集群 主备同步
搞个死循环排队
可重入设计一个字段累加
排它锁
用数据库自身的锁就可以了 行锁 索引
select XX for update
记得 提交
宕机数据库也会自动释放锁
缺点
比其他的更消耗资源
复杂
特点
互斥
安全性
死锁
容错
操作系统
redis
缓存穿透
缓存击穿
缓存雪崩
缓存预热
缓存更新
缓存降级
缓存穿透
https://cloud.tencent.com/developer/article/1666384
memecached
IO 多路复用
https://github.com/yuhaqiang123/my-love
select
O(n)
1024 个fd
poll
没有最大连接数的限制,原因是它是基于链表来存储的
epoll
O(1)
理解为event poll
是事件驱动(每个事件关联上fd)的
就通过一种机制,可以监视多
个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应
的读写操作。
但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件
就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负
责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
进程管理与调度算法
https://github.com/yuhaqiang123/my-love
零拷贝& mmap
Redis
数据结构
String
Hash
set
zset
score
随机层数
只需要调整前后节点指针
不止比较score
还会比较value
场景
成绩
积分
排行榜
List
分页的坑
HyperLogLog
HyperLogLog
记录访问uv
海量数据的计算
速度快。占用空间小
https://www.cnblogs.com/williamjie/p/9505075.html#:~:text=Redis%20HyperLogLog%20%E6%98%AF%E7%94%A8%E6%9D%A5%E5%81%9A%E5%9F%BA%E6%95%B0%E7%BB%9F%E8%AE%A1%E7%9A%84%E7%AE%97%E6%B3%95%EF%BC%8CHyperLogLog%20%E7%9A%84%E4%BC%98%E7%82%B9%E6%98%AF%EF%BC%8C%E5%9C%A8%E8%BE%93%E5%85%A5%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E9%87%8F%E6%88%96%E8%80%85%E4%BD%93%E7%A7%AF%E9%9D%9E%E5%B8%B8%E9%9D%9E%E5%B8%B8%E5%A4%A7%E6%97%B6%EF%BC%8C%E8%AE%A1%E7%AE%97%E5%9F%BA%E6%95%B0%E6%89%80%E9%9C%80%E7%9A%84%E7%A9%BA%E9%97%B4%E6%80%BB%E6%98%AF%E5%9B%BA%E5%AE%9A%20%E7%9A%84%E3%80%81%E5%B9%B6%E4%B8%94%E6%98%AF%E5%BE%88%E5%B0%8F%E7%9A%84%E3%80%82%20%E5%9C%A8%20Redis,%E9%87%8C%E9%9D%A2%EF%BC%8C%E6%AF%8F%E4%B8%AA%20HyperLogLog%20%E9%94%AE%E5%8F%AA%E9%9C%80%E8%A6%81%E8%8A%B1%E8%B4%B9%2012%20KB%20%E5%86%85%E5%AD%98%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%AE%A1%E7%AE%97%E6%8E%A5%E8%BF%91%202%5E64%20%E4%B8%AA%E4%B8%8D%E5%90%8C%E5%85%83%E7%B4%A0
基数个数计算
计算UV 适量
比如每个页面的UV
Geo
https://www.jianshu.com/p/81bf3baa64e5
Pub/Sub
https://blog.csdn.net/qq_41125219/article/details/120299819
已经被抛弃了。。。。
BitMap
BitMap
不光需要记录数据,还需要对数据进行验证的时候使用Bitmaps。
https://www.cnblogs.com/williamjie/p/9505075.html#:~:text=Redis%20HyperLogLog%20%E6%98%AF%E7%94%A8%E6%9D%A5%E5%81%9A%E5%9F%BA%E6%95%B0%E7%BB%9F%E8%AE%A1%E7%9A%84%E7%AE%97%E6%B3%95%EF%BC%8CHyperLogLog%20%E7%9A%84%E4%BC%98%E7%82%B9%E6%98%AF%EF%BC%8C%E5%9C%A8%E8%BE%93%E5%85%A5%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E9%87%8F%E6%88%96%E8%80%85%E4%BD%93%E7%A7%AF%E9%9D%9E%E5%B8%B8%E9%9D%9E%E5%B8%B8%E5%A4%A7%E6%97%B6%EF%BC%8C%E8%AE%A1%E7%AE%97%E5%9F%BA%E6%95%B0%E6%89%80%E9%9C%80%E7%9A%84%E7%A9%BA%E9%97%B4%E6%80%BB%E6%98%AF%E5%9B%BA%E5%AE%9A%20%E7%9A%84%E3%80%81%E5%B9%B6%E4%B8%94%E6%98%AF%E5%BE%88%E5%B0%8F%E7%9A%84%E3%80%82%20%E5%9C%A8%20Redis,%E9%87%8C%E9%9D%A2%EF%BC%8C%E6%AF%8F%E4%B8%AA%20HyperLogLog%20%E9%94%AE%E5%8F%AA%E9%9C%80%E8%A6%81%E8%8A%B1%E8%B4%B9%2012%20KB%20%E5%86%85%E5%AD%98%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%AE%A1%E7%AE%97%E6%8E%A5%E8%BF%91%202%5E64%20%E4%B8%AA%E4%B8%8D%E5%90%8C%E5%85%83%E7%B4%A0
二值计算的场景
https://zhuanlan.zhihu.com/p/315232832#:~:text=bitmap%E6%98%AFr,%E5%BD%95%E7%94%A8%E6%88%B7%E7%AD%BE%E5%88%B0%E6%83%85%E5%86%B5%E3%80%82
https://blog.csdn.net/u011957758/article/details/74783347
底层
SDS
最底层数据结构
SDS
双端链表
ziplist
键值的底层都是SDS
子主题
AOF缓存区
记录本身长度 C需要遍历
修改字符减少内存重新分配
空间预支配
惰性空间释放
二进制安全
C只能保存文本数据 无法保存图片等二进制数据
sds是使用长度去判断
杜绝缓冲区溢出
兼容部分C字符串函数
链表
保存多个客户端的状态信息
列表订阅发布 慢查询 监视器
字典
数据库 哈希键
Hash表节点
hash冲突用单向链表解决
渐进式 rehash
会逐渐rehash 新的键值对全部放到新的hash表
每个字典带 两个hash表
一个平时用 一个rehash时候用
压缩列表
整数集合
锁
https://blog.csdn.net/weixin_30016593/article/details/115502002?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.highlightwordscore&spm=1001.2101.3001.4242.1
与memcahe 对比
常见命令
Keys
setnx
exprie
高可用
持久化
RDB
5分钟一次
冷备
恢复的时候比较快
快照文件生成时间久,消耗cpu
AOF
appendOnly
数据齐全
回复慢文件大
数据初始化
从节点发送命令主节点做bgsave同时开启buffer
数据同步机制
主从同步
指令流
offset
快照同步
RDB
缓冲区
哨兵
集群监控
消息通知
故障转移
配置中心
脑裂
集群
链表
多主
横向扩容
分片
常见问题
缓存雪崩
加随机值
集群部署
很多key 在同一时刻 失效
==》众多流量 同时 ==》直接打到后端DB
解决方案:
过期时间,设置一定范围的随机时间,离散 过期点
==》减少同时失效的概率
降级
缓存击穿
互斥锁
热点数据不失效
key 存在 && 过期时间边界==》大量请求--》直接打到后端DB
解决方案:
使用setnx (set if not exists)
==>来设置一个短期key 锁 && 访问结束 删除锁
缓存穿透
访问不存在key ,流量直接打到后端DB
解决方案:
1、空值存入redis && 过期时间很短
2、布隆姆过滤器==》bitmap
==》不存在的key 直接被过滤掉
(需要懂布隆姆算法原理)
双写一致性
延时双删
并发竞争
分布式锁
大Key
bigkey命令 找到干掉
Redis 4.0引入了memory usage命令和lazyfree机制
value 太大 比如几百兆 or 1G ==>导致网络问题;
造成集群数据量倾斜
解决方案:
1、业务上更小业务单元,就是拆分
2、删除大key 使用 unlink(会另起一个线程执行)
Redis 4.0引入了memory usage命令和lazyfree机制
热点key
缓存时间不失效
多级缓存
布隆过滤器
读写分离
缓存集群中的某个key瞬间被数万甚至十万的并发请求打爆
解决方案:
1、分散成多个子key;数据备份其他节点,业务逻辑层做负载均衡
2、限流熔断保护
3、客户端缓存数据&&设置失效时间
读写分离
布隆过滤器
缓存时间不失效
过期策略
定时删除
消耗内存
创建一个定时器
惰性删除
可能存在大量key
读取的时候--》判断是否过期;过期则删除
定期删除
检查 删除 但是是随机的
每隔时间,遍历数据库==》删除
redis 方案:
惰性 + 定期删除 ==》配合使用==>很好平衡 CPU 和内存
淘汰机制
LUR
最少使用
内存不足--》怎么淘汰内存,以获取新的内存空间给新的key
6种具体策略
noeviction: 不足时,报错 ==>默认策略
allkeys-lru :键空间,移除最近最少使用key
allkeys-random: 键空间,随机删除 某个key
volatile-lru:键空间中设置了过期的,删除最近最少使用key
volatile-random: 在设置了过期的键空间,随机删除key
volatile-ttl: 设置了过期时间的键空间中,更早过期的key 优先删除
allkeys-lru :键空间,移除最近最少使用key
allkeys-random: 键空间,随机删除 某个key
volatile-lru:键空间中设置了过期的,删除最近最少使用key
volatile-random: 在设置了过期的键空间,随机删除key
volatile-ttl: 设置了过期时间的键空间中,更早过期的key 优先删除
获取策略配置: config get maxmemory-policy
备用方案
主从+哨兵+cluster
ecache+Hystrix+降级+熔断+隔离
持久化
持久化
rdb
aof
一般二者结合。rdb (每隔 10分钟备份) + aof (aof fsync 方式)
事务
开始标志:MULTI 结束标志:EXEC
WATCH、DISCARD(取消事务)
限流
setnx ex
zset
窗口滑动
zset会越来越大
令牌
定时push
然后leftpop
问题
空轮训
blpop
空连接异常
重试
漏桶 funnel
make_space 灌水之前调用漏水 腾出空间 取决于流水速率
Hash
原子性有问题
Redis-Cell
redis cell
选择方案
热点key
二级缓存
备份热key 走不同的机器
扩展
跳跃表
令牌
漏桶
scan
多路IO复用
read得读到很多才返回 为0会卡在那 直到新数据来或者链接关闭
写不会阻塞除非缓冲区满了
非阻塞的IO 提供了一个选项 no_blocking 读写都不会阻塞 读多少写多少 取决于内核的套接字字节分配
非阻塞IO也有问题 线程要读数据 读了一点就返回了 线程什么时候知道继续读?写一样
一般都是select解决 但是性能低 现在都是epoll
redis 部署模式
单机模式、主从模式、哨兵模式、集群模式
分布式锁
https://zhuanlan.zhihu.com/p/76294773
https://blog.csdn.net/liu_dong_java/article/details/103411144?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
实现过程
a、获取锁
$value = md5($processid . time()); // 钥匙
不存在则设置 set key value px 1000 nx //毫秒
set key value ex 1000 nx // 秒
setnx key timeout value
b、业务 :需要在 限定时间完成,否则锁失效,
c 、解锁:
if (uniquekey == GET(key))
{
del key;
}
===> 需要 保证这两个 操作是 原子的。都在redis 单线程内执行。===》引入 lua 脚本(redis 支持的)
参考:https://redisbook.readthedocs.io/en/latest/index.html
redis 除了做统计还能做什么
1. Redis能够胜任存储工作
2. Reids应用场景
2.1 基本用户数据存储
hash结构
HGET
HMGET
2.2 实现计数器
INCRBY
HINCRBY
2.3 排行榜
zset
千万甚至是亿的级别
非常棒的平均响应时间(5ms以内)
zadd
ZADD sorted:xjjdog:2021-07 55 dog0
zrevrange
1 介绍
返回指定索引区间元素
ZRANGE key start stop [WITHSCORES]
如果score相同,则按照字典序lexicographical order 排列
默认按照score从小到大,如果需要score从大到小排列,使用ZREVRANGE
2.4 好友关系
zset
zinterstore
取两个集合的交集
获取A和B的共同好友
https://segmentfault.com/a/1190000004260261
set
sinter
获取A和B的共同好友
2.5 统计活跃用户数
bitmap
>SETBIT online:2021-07-23 3876520333 1
>SETBIT online:2021-07-24 3876520333 1
>GETBIT online:2021-07-23 3876520333
1
>BITOP AND active online:2021-07-23 online:2021-07-24
>GETBIT active 3876520333
1
>DEBUG OBJECT online:2021-07-23
Value at:0x7fdfde438bf0 refcount:1 encoding:raw serializedlength:5506446 lru:16410558 lru_seconds_idle:5
(0.96s)
bitmap包含一串连续的2进制数字,使用1bit来表示真假问题。在bitmap上,可以使用and、or、xor等位操作(bitop)。
2.6 分布式锁
2.7 分布式限流
incr key
expire key 1
同样是redisson的RRateLimiter,实现了与guava中类似的分布式限流工具类,使用非常便捷。下面是一个简短的例子:
RRateLimiter limiter = redisson.getRateLimiter("xjjdogLimiter");
// 只需要初始化一次
// 每2秒钟5个许可
limiter.trySetRate(RateType.OVERALL, 5, 2, RateIntervalUnit.SECONDS);
// 没有可用的许可,将一直阻塞
limiter.acquire(3);
2.8 消息队列
list
lpush
rpop
阻塞型
BRPOP
BLPUSH
Redis还有PUB/SUB模式
Redis5.0中,增加了stream类型
2.9 LBS应用
Geo
GEOADD
坐标之间的距离计算
包含关系计算
附近的人等功能
强大的开源方案
PostgreSQL的PostGIS
https://juejin.cn/post/6989108481018036232
文件系统
https://mp.weixin.qq.com/s/UT2JrfpkA5OUC9fJJ_MirQ
常用命令
这个bolg有不少题,可以练一下
awk
分析nginx 日志
top n
占比率等。
crontab
任务书写
查看内存 top 命令等
vim 一些操作
shell 脚本 ==》 这个如果你是高级PHP程序员,应该需要掌握吧
grep 考察
进程通信机制
5种
算法
查找
顺序查找
二分查找
hash 查找
分块查找
排序
3种低级排序
冒泡
选择排序
插入排序
跟冒泡有点类似
希尔排序
3种 高级排序
快速排序
递归
动态规划
归并排序
堆排序
最变态的方法:堆排序
实现
# 堆排序
# 向下调整函数的实现, 此处建立大根堆,可实现数组升序排列
def sift(alist, low, high):
# 假设只有根节点需要调整,两棵子树都是堆
i = low
j = i *2 +1 #j指向i的左子树
tmp = alist[i]
while j <=high:
if j+1<= high and alist[j] < alist[j+1] #右子树比较大,则指向右子树
j = j+1
if alist[j] > tmp: # 若子树的值比较大,则根节点换成子树,然后向下看一层
alist[i] = alist[j]
i = j
j = i *2 +1
else:
alist[i] = tmp # 子树的值小于根节点,则根节点就放在这一层
break
else:
alist[i] = tmp # j越界跳出循环,则把根节点放在叶子节点
def heap_sort(alist):
# 1、建堆
# 先找到最后一个不是叶子节点的根节点,为(n-2)//2 (若叶子节点为i,则他的父节点为(i-1)//2 )
# 再向上循环根节点,从小到大
n = len(alist)
for i in range((n-2)//2, -1, -1):
sift(alist,i,n-1)
# 2、挨个出数,按升序排列
for i in range(n-1, -1, -1):
alist[0], alist[i] = alist[i], alist[0]
sift(alist, 0, i-1)
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20, 13]
heap_sort(li)
print(li)
作者:xiao-xie-shui-bu-xing
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/ge-chong-pai-xu-suan-fa-tu-xie-zong-jie-by-ke-ai-x/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
topK 问题
快排思想解决
堆排序思想解决
遍历
广度优先遍历
深度优先遍历
前序遍历
中序遍历
后序遍历
LeetCode
快慢指针
https://leetcode-cn.com/problems/linked-list-cycle/submissions/
快慢指针一定会相遇么
https://zhuanlan.zhihu.com/p/60736361
线性同余方程 [公式] 是否有解?
大数据
Hive
Hdfs
ClickHouse
Hadoop
Flink
搜索引擎
ES
https://zhuanlan.zhihu.com/p/139762008
全文索引
对比 Mysql 、MongoDB、ES
https://zhuanlan.zhihu.com/p/387891359
https://zhuanlan.zhihu.com/p/353592281
Elasticsearch和MongoDB简要对比
https://www.cnblogs.com/wangzhen3798/p/10032898.html
倒排索引
知识图谱
https://www.cnblogs.com/wangzhen3798/p/10032898.html
https://www.processon.com/view/5bbf0100e4b0bd4db95e28c5?fromnew=1
ElasticSearch 搜索底层原理图
https://www.processon.com/view/6162fd805653bb1336d2913d?fromnew=1
redis、es、rocketmq持久化对照
https://www.processon.com/view/603d9e2d07912913b4f49aec?fromnew=1
ES基础使用学习
https://www.processon.com/view/607192c5e0b34d78c0143181?fromnew=1
索引 底层数据结构 对比
https://blog.csdn.net/weixin_39920403/article/details/110647101
sql to ES DSL
https://elasticsearch.cn/article/114
MongoDB
PG
Luceue
Kibanna
Logstash
架构演进
单体
微服务
https://github.com/yuhaqiang123/my-love
子主题
网格
服务治理框架
Dubbo
Docker && K8s
场景方案
秒杀
https://github.com/AobingJava/JavaFamily
秒杀架构
https://github.com/yuhaqiang123/my-love
https://mp.weixin.qq.com/s/KWb3POodisbOEsQVblsoGw
https://mp.weixin.qq.com/s/RRHN8t017ofOvb4nvlCStg
购物车
ID生成
如何设计一个服务框架
https://github.com/yuhaqiang123/my-love
订单场景
https://blog.csdn.net/weixin_42405670/article/details/117898352
下单锁定商品、优惠券、红包等
https://www.processon.com/view/link/5fb362c85653bb29a8f9966f
电商-订单管理
https://www.processon.com/view/5fbc7a62f346fb4e415b96a4?fromnew=1
下单流程下单流程
https://www.processon.com/view/link/5fb362c85653bb29a8f9966f
遇到的坑
前端
监测
普罗米修斯
ELK
CI
持续集成&发布等
排期&&项目管理
需求评审
评估 产出
取舍
排期
取舍 & 时间安排
owner
评估项目
分配精力
得到产出
与领导对齐 KPI
对齐领导OKR
项目
友空间
美菜商城
贝壳
看点
内容中台
问答项目
个人项目
???
公司
自我评价&&自我介绍
影响深刻的问题 项目
压测
https://mp.weixin.qq.com/s/RzJkQuMAszkC8jw8hF-k1w
子主题
0 条评论
下一页