首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
140 阅读
2
php接口优化 使用curl_multi_init批量请求
131 阅读
3
2024年备考系统架构设计师
102 阅读
4
《从菜鸟到大师之路 ElasticSearch 篇》
102 阅读
5
PHP 文件I/O
89 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
785
篇文章
累计收到
8
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
785
篇与
的结果
2023-08-12
MYSQL[快问快答系列]
[MYSQL[快问快答系列]](https://learnku.com/articles/75347)4 核 16GB 内存 1TB 固态硬盘,请给我 mysql8.0 的最优配置 my.cnf[mysqld]基本设置port = 3306user = mysqldefault_storage_engine = InnoDBsocket = /var/lib/mysql/mysql.sockpid-file = /var/lib/mysql/mysql.pid日志文件设置log-error = /var/log/mysql/error.logslow_query_log = 1slow_query_log_file = /var/log/mysql/mysql-slow.loglong_query_time = 2log_queries_not_using_indexes = 1缓存设置thread_cache_size = 128table_open_cache = 2048table_definition_cache = 2048table_open_cache_instances = 64query_cache_type = 1query_cache_size = 64Mquery_cache_limit = 4MInnoDB存储引擎设置innodb_buffer_pool_size = 12G //缓冲池大小innodb_log_file_size = 2G //事务日志文件大小innodb_flush_log_at_trx_commit = 1 //2为异步,有风险;1为同步,性能较差innodb_file_per_table = 1 //每个InnoDB表创建单独的数据文件。innodb_flush_method = O_DIRECT //指定InnoDB使用的磁盘刷新方法。O_DIRECT参数表示数据被直接写入磁盘而不是被缓存到操作系统缓存中。innodb_io_capacity = 2000 //指定InnoDB磁盘IO容量的预估值。innodb_io_capacity_max = 4000 //指定InnoDB磁盘IO容量的上限值。线程和连接设置max_connections = 500 //允许的最大客户端连接数max_user_connections = 1000 //每个mysql用户允许的最大连接数。如果没有单独设置,则使用全局max_connections值。thread_stack = 512K //线程分配的堆栈空间thread_cache_size = 128 //MySQL线程缓存的大小。wait_timeout = 600 //连接在没有活动操作时被关闭之前的等待时间。interactive_timeout = 600connect_timeout = 60其他设置character_set_server = utf8mb4collation_server = utf8mb4_unicode_ci执行一条 select 语句,期间发生了什么?Mysql 客户端与 Mysql 服务端通过三次握手建立 TCP 连接验证账号密码查询缓存,如果命中直接返回 (MySQL 8.0 版本直接将查询缓存删掉了)解析器阶段,进行词法分析,生成语法树预处理阶段,检查 SQL 语句中的表或者字段是否存在,将 select 中的 符号扩展为表上的所有列优化器阶段,基于查询成本的考虑,决定使用什么索引执行器阶段,开始与存储引擎交互,从存储引擎读取记录,返回给客户端如何查看 MySQL 服务被多少个客户端连接了?show processlist;空闲连接会一直占用着吗?MySQL 定义了空闲连接的最大空闲时长,由 wait_timeout 参数控制的,默认值是 8 小时(28880 秒),如果空闲连接超过了这个时间,连接器就会自动将它断开。mysql> show variables like 'wait_timeout';Variable_nameValuewait_timeout28800MySQL 的连接数有限制吗?最大连接数由 max_connections 参数控制,超过这个值,系统就会拒绝接下来的连接请求,并报错提示 “Too many connections”。mysql> show variables like 'max_connections';Variable_nameValuemax_connections500怎么解决长连接占用内存的问题?定期断开长连接客户端主动重置连接explain 命令possible_keys 字段表示可能用到的索引key 字段表示实际用的索引,如果这一项为 NULL,说明没有使用索引;key_len 表示索引的长度,根据 key_len 长度来分析联合索引使用了几个rows 表示扫描的数据行数。type 表示数据扫描类型extra 额外信息type 执行效率从低到高的顺序为:All 全表扫描index 全索引扫描 比全表扫描好一些,好处是不用再排序range 索引范围扫描 尽量让 SQL 查询可以使用到 range 这一级别及以上的 type 访问方式ref 非唯一索引扫描eq_ref 主键或唯一索引扫描,通常使用在多表联查中const 结果只有一条的主键或唯一索引扫描extra:覆盖索引 Extra:Using index 效率不错索引下推 Extra:Using index condition文件排序 Extra:Using filesort 常见于 group by 操作 效率低临时表 Extra:Using temporary 常见于 group by/order by 操作 效率低查询一次数据最多需要多少次 IOB+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4 次什么是回表先检二级索引中的 B+Tree 的索引值,找到对应的叶子节点,然后获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫回表,也就是说要查两个 B+Tree 才能查到数据。什么是覆盖索引在二级索引的 B+Tree 就能查询到结果的过程就叫作覆盖索引,不需要回表。什么是索引下推MySQL 5.6 引入的索引下推优化, 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。字符集 utf8,utf8mb4,ascii 一个字符分别占用多少字节?utf8 3 个utf8mb4 4 个 允许存储 emoji 表情ascii 1 个怎么提高这条 SQL 效率select * from order where status = 1 order by create_time asc建立 status,create_time 联合索引,避免文件排序什么时候使用索引字段有唯一性限制的经常用于 WHERE 查询条件的字段经常用于 GROUP BY 和 ORDER BY 的字段什么时候不使用索引WHERE 条件,GROUP BY,ORDER BY 里用不到的字段字段中存在大量重复数据,不需要创建索引表数据太少的时候,不需要创建索引经常更新的字段不用创建索引索引列为什么最好设置为 Not Null索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化NULL 值是一个没意义的值,但是它会占用物理空间,至少每行都会用 1 字节空间存储 NULL 值列表索引什么时候失效like % xx 或者 like % xx%对索引列做了计算、函数、类型转换操作没有按照最左优先的方式进行索引的匹配在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列Innodb 为什么选择 B+treeHashHash 在做等值查询的时候效率贼快,搜索复杂度为 O (1)。但是 Hash 表不适合做范围查询,它更适合做等值的查询二叉树数据量越大,二叉树高越高,磁盘 IO 越多,B+Tree 再千万级别的数据量下只用 3-4 层B Tree相同数据量时,B+Tree 树高比 BTree 低,磁盘 IO 次数更少B+Tree 叶子节点用双向链表串起来,适合范围查询,BTree 无法做到这点如何添加测试数据CREATE TABLE person(id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键', person_id tinyint not null comment '用户id', person_name VARCHAR(200) comment '用户名称', gmt_create datetime comment '创建时间', gmt_modified datetime comment '修改时间') comment '人员信息表';添加一条数据insert into person values(1, 1,'user_1', NOW(), now());以下 sql 执行 20 次 约等于 100 万条数据执行 24 次 1600 万条数据INSERT INTO person ( person_id, person_name, gmt_create, gmt_modified ) SELECT LEFT( rand()* 10, 10 ) AS person_id,concat( 'user_', LEFT ( rand()* 10, 10 ) % 2048 ),date_add( gmt_create, INTERVAL + @i cast( rand() 100 AS signed ) SECOND ),date_add(date_add( gmt_modified, INTERVAL + @i * cast( rand()* 100 AS signed ) SECOND ), INTERVAL + cast( rand()* 1000000 AS signed ) SECOND ) FROMperson;MySQL 单表为什么最好不要超过 2000W超过了这个值可能会导致 B + 树层级更高,影响查询性能。MySQL 使用 like “% x“,索引一定会失效吗?不一定,如果扫描了二级索引就能得到结果,就不用回表,直接返回数据,这个时候 explain 的 type 是 indexcount (*) 和 count (1) 有什么区别?哪个性能最好?count() 执行过程跟 count (1) 执行过程基本一样的,性能没有什么差异。而且 MySQL 会对 count () 和 count (1) 有个优化,如果有多个二级索引的时候,优化器会使用 key_len 最小的二级索引进行扫描。只有当没有二级索引的时候,才会采用主键索引来进行统计。如何优化 count (*)?近似值explain select count(*) from t_order会返回一个近似值 rows额外表保存计数值插入一条记录的同时,将计数表字段 + 1, 新增和删除的时候需要额外维护这个计数器,存在 redis 也行事务有哪些特性?原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成一致性(Consistency):事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。隔离性(Isolation):每个事务都有一个完整的数据空间,对其他并发事务是隔离的。持久性(Durability):事务处理结束后,对数据的修改就是永久的InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?持久性是通过 redo log (重做日志)来保证的;原子性是通过 undo log(回滚日志) 来保证的;隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;一致性则是通过持久性 + 原子性 + 隔离性来保证;事务的隔离级别有哪些?读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;读提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;MySQL InnoDB 怎么避免幻读现象?针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。针对当前读(select … for update 等语句),是通过 next-key lock(记录锁 + 间隙锁)方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。快照读和当前读有什么区别?MySQL 里除了普通查询是快照读,其他都是当前读,比如 update、insert、delete,这些语句执行前都会查询最新版本的数据。另外,select ... for update 这种查询语句是当前读,每次执行的时候都是读取最新的数据。既然备份数据库数据的时候,使用全局锁会影响业务,那有什么其他方式可以避免?在使用 mysqldump 时加上 –single-transaction 参数的时候,就会在备份数据库之前先开启事务。因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。MySQL 死锁了,怎么办?设置事务等待锁的超时时间,当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。在 InnoDB 中,参数 innodb_lock_wait_timeout 是用来设置超时时间的,默认值时 50 秒。开启主动死锁检测。主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑,默认就开启。分析产生死锁的业务逻辑,考虑怎么去掉 select …for update 导致产生的死锁为什么需要 undo log?实现事务回滚,保障事务的原子性。。实现 MVCC(多版本并发控制)关键因素之一。为什么需要 缓冲池 Buffer Pool?当读取数据时,如果数据存在于 Buffer Pool 中,客户端就会直接读取 Buffer Pool 中的数据,否则再去磁盘中读取。当修改数据时,如果数据存在于 Buffer Pool 中,那直接修改 Buffer Pool 中数据所在的页,然后将其页设置为脏页,为了减少磁盘 I/O,不会立即将脏页写入磁盘,后续由后台线程选择一个合适的时机将脏页写入到磁盘Buffer Pool 除了缓存「索引页」和「数据页」,还包括了 Undo 页,插入缓存、自适应哈希索引、锁信息等等。查询一条记录,就只需要缓冲一条记录吗?不对,当我们查询一条记录时,InnoDB 是会把整个页的数据加载到 Buffer Pool 中为什么需要 redo log ?为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,InnoDB 引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以 redo log 的形式记录下来当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。redo log 和 undo log 区别在哪?redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;事务提交之前发生了崩溃,重启后会通过 undo log 回滚事务,事务提交之后发生了崩溃,重启后会通过 redo log 恢复事务,如下图:redo log 什么时候刷盘?MySQL 正常关闭时;当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘(这个策略可由 innodb_flush_log_at_trx_commit 参数控制,下面会说)。为什么需要 binlog ?binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。redo log 和 binlog 有什么区别?binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用,用于备份恢复、主从复制;redo log 是 Innodb 存储引擎实现的日志,用于掉电等故障恢复。如果不小心整个数据库的数据被删除了,能使用 redo log 文件恢复数据吗?不可以使用 redo log 文件恢复,只能使用 binlog 文件恢复。主从复制是怎么实现?写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。回放 Binlog:回放 binlog,并更新存储引擎中的数据。从库是不是越多越好?不是的。因为从库数量增加,从库连接上来的 I/O 线程也比较多,主库也要创建同样多的 log dump 线程来处理复制的请求,对主库资源消耗比较高,同时还受限于主库的网络带宽。所以在实际使用中,一个主库一般跟 2~3 个从库(1 套数据库,1 主 2 从 1 备主),这就是一主多从的 MySQL 集群结构。为什么需要两阶段提交?MySQL 会同时维护 binlog 日志与 InnoDB 的 redo log,为了保证这两个日志的一致性,MySQL 使用了内部 XA 事务MySQL 磁盘 I/O 很高,有什么优化的方法?设置组提交的两个参数: binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 参数,延迟 binlog 刷盘的时机,从而减少 binlog 的刷盘次数。这个方法是基于 “额外的故意等待” 来实现的,因此可能会增加语句的响应时间,但即使 MySQL 进程中途挂了,也没有丢失数据的风险,因为 binlog 早被写入到 page cache 了,只要系统没有宕机,缓存在 page cache 里的 binlog 就会被持久化到磁盘。将 sync_binlog 设置为大于 1 的值(比较常见是 100~1000),表示每次提交事务都 write,但累积 N 个事务后才 fsync,相当于延迟了 binlog 刷盘的时机。但是这样做的风险是,主机掉电时会丢 N 个事务的 binlog 日志。将 innodb_flush_log_at_trx_commit 设置为 2。表示每次事务提交时,都只是缓存在 redo log buffer 里的 redo log 写到 redo log 文件,注意写入到「 redo log 文件」并不意味着写入到了磁盘,因为操作系统的文件系统中有个 Page Cache,专门用来缓存文件数据的,所以写入「 redo log 文件」意味着写入到了操作系统的文件缓存,然后交由操作系统控制持久化到磁盘的时机。但是这样做的风险是,主机掉电的时候会丢数据。你知道 mysql 主从延迟吗?有些时候延迟的时间还会很长。遇到这种情况咋么办?多线程复制确保使用了多线程复制,并且已经按照手册查看了如何调整各种选项以从中获得最佳效率。调整 binlog 格式调整为 statement 减小 binlog 容量临时降低持久化要求可以临时设置sync_binlog=0,innodb_flush_log_at_trx_commit=0以提高复制速度。怎么定位运行中的 MySQL 使用哪个配置文件which mysqld/usr/sbin/mysqld/usr/sbin/mysqld --verbose --help | grep -A 1 'Default options'Default options are read from the following files in the given order:/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf 为什么不建议字段格式为 null如果查询中包含可为 NULL 的列,对 MySQL 来说更难优化,因为可为 NULL 的列使得索引、索引统计和值比较都更复杂。可为 NULL 的列会使用更多的存储空间,在 MySQL 里也需要特殊处理。储存财务数据,BIGINT 还是 DECIMAL假设要存储财务数据并精确到万分之一分,则可以把所有金额乘以一百万然后将结果存储在 BIGINT 里,这样可以同时避免浮点存储计算不精确和 DECIMAL 精确计算代价高的问题。VARCHAR 和 CHAR 的区别VARCHARVARCHAR 需要额外使用 1 或 2 字节在每行数据前记录字符串的长度:如果最大长度 <=255 字节,则只使用 1 字节表示,否则使用 2 字节。VARCHAR 节省了存储空间,所以对性能也有帮助。但是,由于行是可变长度的,在更新时可能会增长,这会导致 InnoDB 需要分割页面来容纳行,InnoDB 将过长的 VARCHAR 值存储为 BLOBCHAR当存储 CHAR 值时,MySQL 删除所有尾随空格。如果需要进行比较,值会用空格填充。CHAR 适合存储用户密码的 MD5 值。对于经常修改的数据,CHAR 也比 VARCHAR 更好,因为固定长度的行不容易出现碎片。对于非常短的列,CHAR 也比 VARCHAR 更高效;设计为只保存 Y 和 N 的值的 CHAR(1)在单字节字符集 [1] 中只使用 1 字节,但 VARCHAR(1)需要 2 字节如何查询各个数据表储存大小mysql> select table_schema as '数据库', table_name as '表名', table_rows as '记录数', truncate(data_length/1024/1024, 2) as '数据容量(MB)', truncate(index_length/1024/1024, 2) as '索引容量(MB)' from information_schema.tables where table_schema='test' order by data_length desc, index_length desc;数据库表名记录数数据容量(MB)索引容量(MB)testwd_admin_log3830.200.01DATETIME 还是 TIMESTAMPDATETIME可以保存大范围的数值,从 1000 年到 9999 年,精度为 1 微秒。它以 YYYYMMDDHHMMSS 格式存储压缩成整数的日期和时间,且与时区无关。这需要 8 字节的存储空间。TIMESTAMP存储自 1970 年 1 月 1 日格林尼治标准时间(GMT)午夜以来经过的秒数,只使用 4 字节的存储空间,只能表示从 1970 年到 2038 年 1 月 19 日,MySQL 提供 FROM_UNIXTIME () 函数来将 UNIX 时间戳转换为日期,并提供了 UNIX_TIMESTAMP () 函数将日期转换为 UNIX 时间戳。结论使用带符号的 32 位 INT,可以表达直到 2038 年的时间。使用无符号的 32 位 INT,可以表达直到 2106 年的时间。如果使用 64 位,还可以超出这些范围。这一做法越来越流行。可以对保存 md5 (),sha1 (),uuid () 的列做索引吗?这些函数生成的新值会任意分布在很大的空间内,这会减慢INSERT 和某些类型的 SELECT 查询的速度因为插入的值会写到索引的随机位置,所以会使得 INSERT 查询变慢。这会导致页分裂、磁盘随机访问,以及对于聚簇存储引擎产生聚簇索引碎片。SELECT 查询也会变慢,因为逻辑上相邻的行会广泛分布在磁盘和内存中。IPV4 地址用什么数据类型?用过函数转成 int 然后用 unsigned int 存储MySQL schema 设计中的有什么骚操作 (错误示范)?太多的列MySQL 的存储引擎 API 通过在服务器和存储引擎之间以行缓冲区格式复制行来工作,InnoDB 的行格式总是需要转换的。这种转换的成本取决于列数。太多的联接MySQL 限制每个联接有 61 个表全能的枚举如何不停机不锁表地更新表结构?pt-online-schema-change: 原理是使用触发器,对已经使用触发器的表不太兼容gh-ost: 原理是使用 binlog, 对使用外键的表不太兼容怎么选择如果你正在运行许多已存在外键的旧数据库,并且删除外键是很困难的,那么会发现 pt-online-schema-change 已经尝试对外键提供更广泛的支持,但你必须承担为数据完整性和正常运行时间选择最安全选项的认知负担。此外,gh-ost 利用 binlog 来完成其工作,因此如果由于某种原因无法访问这些日志,pt-online-schema-change 仍然是一个可行的选项。INNODB 自适应哈希索引特性?当 InnoDB 发现某些索引值被非常频繁地被访问时,它会在原有的 B-tree 索引之上,在内存中再构建一个哈希索引。这就可以实现非常快速的哈希查找。这个过程是完全自动化的,用户可以通过参数关闭这个特性。如何减少索引和数据的碎片通过执行 OPTIMIZE TABLE 或者导出再导入的方式来重新整理数据。联接查询怎么优化?确保 ON 或者 USING 子句中的列上有索引。确保任何 GROUP BY 和 ORDER BY 中的表达式只涉及一个表中的列,这样 MySQL 才有可能使用索引来优化这个过程。怎么优化大表 limit offset错误示范select id,description from film order by title limit 50, 5正确示范select id,description from film inner join (select id from film order by title limit 50,5) as lim using (id)复制如何工作主库把数据更改记录到 binlog从库启动线程 1 把主库的 binlog 复制到自己的中继日志从库启动线程 2 重放中继日志binlog_format 有多少种日志格式?STATEMENT表示在 binlog 文件中只记录 SQL 语句。这是默认值,优点是简单紧凑容量小,其最大的弊端则在于会遇到某些具有 “不确定性” 的 SQL 语句问题ROW表示在 binlog 文件中只记录受影响的行。在这种格式下,MySQL 会将对数据的更改记录为行级别的操作。这种格式可以更准确地记录数据更改,但会导致 binlog 文件更大。MIXED表示在 binlog 文件中既记录 SQL 语句,又记录受影响的行。MySQL 会自动选择适当的格式来记录数据更改。这是最常用的格式,因为它可以平衡可读性和性能。结论我们 (高性能 MYSQL 第四版) 建议坚持使用基于行的复制 ROW,除非某些场景下明确需要临时使用基于语句的复制。基于行的复制提供了最安全的数据复制方法。怎么保证崩溃后的复制安全保证每个undo log都被同步地写到磁盘,增加磁盘写入操作频次,确保数据持久性innodb_flush_log_at_trx_commit=1每次事务执行的时候都会把二进制日志同步写入磁盘。增加磁盘写入操作频次,防止丢失事务sync_binlog=1使用 InnoDB 存储引擎存储中继日志信息,提供更好的可靠性和性能。relay_log_info_repository=TABLE在复制过程中发生错误时自动尝试使用中继日志进行恢复relay_log_recovery=ON延迟复制有什么用想象一下这样的场景,你正在处理大量数据,突然意外地做了一些变更:删除了一个表。从备份中恢复可能需要几个小时。如果使用了延迟复制的副本,则可以找到 DROP TABLE 语句对应的 GTID,使副本服务器的复制运行到表被删除之前的时间点,这会大大减少修复时间。什么是多线程复制?最新的 MySQL 版本则提供了多线程复制能力,可以在副本端运行多个 SQL 线程,从而加快本地中继日志的应用。什么是半同步复制?在半同步复制中,主服务器会等待至少一个从服务器将更新成功复制后,才会返回客户端。确保至少一个从服务器成功复制了更新,降低故障恢复的成本,缺点是会影响主服务器的性能
2023年08月12日
11 阅读
0 评论
0 点赞
2023-08-12
HTTP[快问快答系列]
[HTTP[快问快答系列]](https://learnku.com/articles/75423)键入网址到网页显示,期间发生了什么?浏览器解析请求的 URLhttp: + // + domain.com + / + index.html协议 + // + 服务器地址 + / + 文件路径生成 HTTP 请求报文GET / HTTP/1.1Accept: /DNS 查询浏览器先查有没这个域名的缓存,如果没有就去问操作系统层面有没这个域名的缓存,如果没有就去操作系统的 hosts 文件查询有没配置.如果没有就去本地 DNS 服务器 (我电脑默认自动获取)如果本地 DNS 服务器也没有域名的缓存就会去问根服务器拿 IP根服务器不负责解析域名,只返回顶级域名的服务器地址,比如.com 域名的服务器地址本地 DNS 服务器去问.com 域名服务器地址拿 IP.com 域名服务器返回负责这个二级域名的 DNS 服务器地址本地 DNS 服务器去问二级域名 DNS 服务器拿 IP成功拿到 IP 并在本地 DNS 服务器,浏览器和操作系统都缓存起来协议栈浏览器通过 DNS 查询到的 IP 和解析 URL 查询到的端口用操作系统提供的 socket 库连接服务器,通过三次握手建立 tcp 连接,客户端和服务器双方生成通信 socket 文件$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_connect($socket, 'ip', '端口');TCP 层 可靠传输建立好 tcp 连接之后,HTTP 报文加上 TCP 报文头部,如果报文长度超过了 MSS 长度就会拆解分包发送IP 层 远程定位TCP 报文头部加上 IP 报文头部MAC 层 两点传输IP 报文头部加上 MAC 报文头部网卡把报文转换成电信号,发送到交换机,再发送到路由器,路由器转发上层路由器一直到达服务器服务器按同样的步骤组装返回报文,原路返回逐层去掉头部最终返回到浏览器的 http 报文长这个样子HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Length: 155Connection: close An Example PageHello World, this is a very simple HTML document.GET 与 POST 的区别GET浏览器对 GET 请求的 URL 会有长度限制,对 GET 请求可以缓存,也可以保存书签,历史记录,只支持 url 编码POSTPOST 请求的数据在浏览器 URL 上不可见,支持 url 编码,multipart/form-data 等编码,总结以上是 GET 和 POST 在浏览器上的区别,在 HTTP 协议上,并没有本质的区别,一般 GET 用来获取数据,POST 用来提交数据,GET 也可以像 POST 一样传 body, 只不过 RFC 规范不建议你这么做HTTP 缓存有哪些实现方式?强制缓存Cache-Control 是 HTTP/1.1 的标准,而 Expires 则是 HTTP/1.0 的标准,Cache-Control 的优先级高于 Expires。通常使用 Cache-Control, 比较灵活。Cache-Control:public:响应可以被客户端和代理服务器缓存。private:响应只能被客户端缓存,不能被代理服务器缓存。no-cache:客户端和代理服务器都不能缓存响应,需要重新获取。no-store:响应不能被缓存或存储。max-age:响应的最大有效时间,单位为秒。s-maxage:覆盖 max-age,仅适用于共享缓存,例如代理服务器。Expires:过期时间:响应的绝对过期时间,使用 GMT 格式表示。协商缓存协商缓存需要配合强制缓存中 Cache-Control 来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。服务器根据一下两种方式判断文件没有修改则返回 304 Not Modified,不会返回资源 1.请求头If-Modified-Since和响应头Last-Modified 2.请求头If-None-Match与响应头部ETag HTTP 常见的状态码有哪些?1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。200 : 表示一切正常。204 : 与 200 OK 基本相同,但响应头没有 body 数据206 : 应用于 HTTP 分块下载或断点续传301 : 永久重定向302 : 临时重定向,说明请求的资源还在304 : 表示资源未修改,重定向已存在的缓冲文件400 : 客户端请求的报文有错误403 : 服务器禁止访问这个资源404 : 资源在服务器上不存在500 : 服务器发生了错误501 : 客户端请求的功能服务端还没法开发好502 : phpfpm 发生错误时,nginx 返回的状态码503 : 服务器当前很忙,暂时无法响应客户端HTTP/1.1 相比 HTTP/1.0 提高了什么性能?使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。HTTP/2 做了什么优化?HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。头部压缩HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。二进制格式全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧,收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率并发传输引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。服务器推送主动向客户端发送消息。HTTP/2 有什么缺陷?HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在 “队头阻塞” 的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。所以,一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。HTTP/3 做了哪些优化?无队头阻塞使用 QUIC 协议 底层是 UDP连接迁移 对移动设备非常友好HTTPS 是如何建立连接的?其间交互了什么?首先三次握手建立 TCP 连接,成功之后马上建立 SSL/TCS 连接SSL/TLS 协议基本流程:客户端向服务器索要并验证服务器的公钥。双方协商生产「会话秘钥」。双方采用「会话秘钥」进行加密通信。SSL/TLS 协议详细流程:ClientHello首先,由客户端向服务器发起 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:(1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。(2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。(3)客户端支持的密码套件列表,如 RSA 加密算法。SeverHello服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:(1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。(2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。(3)确认的密码套件列表,如 RSA 加密算法。(4)服务器的数字证书。客户端回应客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:(1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。(2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。(3)客户端握手结束通知,表示客户端的握手阶段已经结束。服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。服务器的最后回应服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。然后,向客户端发送最后的信息:(1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。(2)服务器握手结束通知,表示服务器的握手阶段已经结束。至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」进行对称加密内容。CA 证书签发过程首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;最后将 Certificate Signature 添加在文件证书上,形成数字证书;吐槽一下动动手的事情竟然要卖几千块一年客户端校验 CA 证书的流程是怎样的?首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。HTTPS 一定安全可靠吗?不一定,如果客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个中间人服务器,形成中间商赚差价,简称中间人攻击客户端向中间人服务器发起 https 请求中间人服务器返回自己的 CA 证书成功建立连接中间人成功解密获取客户端发送的加密报文中间人服务器再跟目标服务器建立 https 连接转发客户端的数据给目标服务器转发目标服务器的报文给客户端这种攻击的前提是你信任了中间人服务器的 CA 证书,或者被木马植入了中间人的 CA 证书,https 协议本身是没漏洞的,中间人攻击本质是利用了客户端的漏洞,不关 https 的事情为什么抓包工具能截取 HTTPS 数据?工作原理跟中间人攻击一致如何避免被中间人抓取数据?通过 HTTPS 双向认证来避免这种问题。这样客户端也要有自己的 CA 证书,双方交换证书确认身份再建立连接
2023年08月12日
11 阅读
0 评论
0 点赞
2023-08-12
Redis[快问快答系列]
[Redis[快问快答系列]](https://learnku.com/articles/75382)什么是 Redis?Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。Redis 提供了多种数据类型来支持不同的业务场景,比如 String (字符串)、Hash (哈希)、 List (列表)、Set (集合)、Zset (有序集合)、Bitmaps(位图)、HyperLogLog(基数统计)、GEO(地理信息)、Stream(流),并且对数据类型的操作都是原子性的,因为执行命令由单线程负责的,不存在并发竞争的问题。除此之外,Redis 还支持事务 、持久化、Lua 脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布 / 订阅模式,内存淘汰机制、过期删除机制等等。Redis 和 Memcached 有什么区别?Memcached 只支持最简单的 key-value 数据类型Redis 支持数据的持久化,Memcached 重启或者挂掉后,数据就没了Redis 原生支持集群模式,Memcached 没有原生的集群模式Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持为什么用 Redis 作为 MySQL 的缓存?Redis 具备高性能,高并发,Redis 单机的 QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w。Redis 数据类型以及使用场景分别是什么?String:缓存对象:SET user:1 '{"name":"xiaolin", "age":18}'计数器:INCR count:1001分布式锁:SET lock_key unique_value NX PX 10000共享 session: 适用分布式系统List:消息队列:消息保序:使用 LPUSH + RPOP;阻塞读取:使用 BRPOP;重复消息处理:生产者自行实现全局唯一 ID;消息的可靠性:使用 BRPOPLPUSHHash:缓存对象一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储。存储一个哈希表uid:1的键值HMSET uid:1 name Tom age 152存储一个哈希表uid:2的键值HMSET uid:2 name Jerry age 132获取哈希表用户id为1中所有的键值HGETALL uid:11) "name"2) "Tom"3) "age"4) "15"购物车添加商品:HSET cart:{用户id} {商品id} 1添加数量:HINCRBY cart:{用户id} {商品id} 1商品总数:HLEN cart:{用户id}删除商品:HDEL cart:{用户id} {商品id}获取购物车所有商品:HGETALL cart:{用户id}Set:聚合计算场景主从集群中,为了避免主库因为 Set 做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计点赞uid:1 用户对文章 article:1 点赞SADD article:1 uid:1uid:1 取消了对 article:1 文章点赞。SREM article:1 uid:1获取 article:1 文章所有点赞用户 :SMEMBERS article:11) "uid:3"2) "uid:2"获取 article:1 文章的点赞用户数量:SCARD article:1(integer) 2判断用户 uid:1 是否对文章 article:1 点赞了:SISMEMBER article:1 uid:1(integer) 0 # 返回0说明没点赞,返回1则说明点赞了共同关注Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等。uid:1 用户关注公众号 id 为 5、6、7、8、9SADD uid:1 5 6 7 8 9uid:2 用户关注公众号 id 为 7、8、9、10、11SADD uid:2 7 8 9 10 11获取共同关注SINTER uid:1 uid:21) "7"2) "8"3) "9"给 uid:2 推荐 uid:1 关注的公众号:SDIFF uid:1 uid:21) "5"2) "6"验证某个公众号是否同时被 uid:1 或 uid:2 关注:SISMEMBER uid:1 5(integer) 1 # 返回0,说明关注了SISMEMBER uid:2 5(integer) 0 # 返回0,说明没关注抽奖活动存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。key 为抽奖活动名,value 为员工名称,把所有员工名称放入抽奖箱 :SADD lucky Tom Jerry John Sean Marry Lindy Sary Mark(integer) 5如果允许重复中奖,可以使用 SRANDMEMBER 命令。抽取 1 个一等奖:SRANDMEMBER lucky 11) "Tom"抽取 2 个二等奖:SRANDMEMBER lucky 21) "Mark"2) "Jerry"抽取 3 个三等奖:SRANDMEMBER lucky 31) "Sary"2) "Tom"3) "Jerry"如果不允许重复中奖,可以使用 SPOP 命令。抽取一等奖1个SPOP lucky 11) "Sary"抽取二等奖2个SPOP lucky 21) "Jerry"2) "Mark"抽取三等奖3个SPOP lucky 31) "John"2) "Sean"3) "Lindy"Zset:排行榜arcticle:1 文章获得了200个赞ZADD user:xiaolin:ranking 200 arcticle:1文章 arcticle:1 新增一个赞ZINCRBY user:xiaolin:ranking 1 arcticle:1查看某篇文章的赞数ZSCORE user:xiaolin:ranking arcticle:4获取文章赞数最多的 3 篇文章ZREVRANGE user:xiaolin:ranking 0 2 WITHSCORES获取100赞到200 赞的文章ZRANGEBYSCORE user:xiaolin:ranking 100 200 WITHSCORES电话和姓名排序使用有序集合的 ZRANGEBYLEX 或 ZREVRANGEBYLEX 可以帮助我们实现电话号码或姓名的排序BitMap:签到第一步,执行下面的命令,记录该用户 6 月 3 号已签到。SETBIT uid:sign:100:202206 2 1第二步,检查该用户 6 月 3 日是否签到。GETBIT uid:sign:100:202206 2 第三步,统计该用户在 6 月份的签到次数。BITCOUNT uid:sign:100:202206用户登录状态第一步,执行以下指令,表示用户已登录。SETBIT login_status 10086 1第二步,检查该用户是否登陆,返回值 1 表示已登录。GETBIT login_status 10086第三步,登出,将 offset 对应的 value 设置成 0。SETBIT login_status 10086 0布隆过滤器HyperLogLog:只需要花费 12 KB 内存,就可以计算接近 2^64 个元素的基数,统计结果是有一定误差的,标准误算率是 0.81%。百万计网页 UV 计数在统计 UV 时,你可以用 PFADD 命令把访问页面的每个用户都添加到 HyperLogLog 中。PFADD page1:uv user1 PFADD page1:uv user2用 PFCOUNT 命令直接获得 page1 的 UV 值了PFCOUNT page1:uvGEO:GEO 本身并没有设计新的底层数据结构,而是直接使用了 Sorted Set 集合类型。查找用户附近的网约车把 ID 号为 33 的车辆的当前经纬度位置存入 GEO 集合中:GEOADD cars:locations 116.034579 39.030452 33当用户想要寻找自己经纬度(116.054579,39.030452 )为中心的 5 公里内的车辆信息GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10Stream:消息队列 比 list 高级Redis 线程模型Redis 单线程指的是「接收客户端请求 -> 解析请求 -> 进行数据读写等操作 -> 发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。Redis 程序不是单线程的,后台还会有三个线程处理关闭文件,AOF 刷盘,释放内存Redis 采用单线程为什么还这么快?Redis 采用单线程模型可以避免了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。Redis 采用了 I/O Epoll 多路复用机制处理大量的客户端 Socket 请求Redis 6.0 之后为什么引入了多线程?在 Redis 6.0 版本之后,也采用了多个 I/O 线程来处理网络请求,** 但是对于命令的执行,Redis 仍然使用单线程来处理,Redis 6.0 版本引入的多线程 I/O 特性对性能提升至少是一倍以上。Redis 如何实现数据不丢失?AOF 日志:每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RBD 的优点;AOF 日志是如何实现的?Redis 在执行完一条写操作命令后,就会把该命令以追加的方式写入到一个文件里,然后 Redis 重启时,会读取该文件记录的命令,然后逐一执行命令的方式来进行数据恢复。Redis 提供了 3 种 AOF 写回硬盘的策略,在 Redis.conf 配置文件中的 appendfsync 配置项Always,每次写操作命令执行完后,同步将 AOF 日志数据写回硬盘;Everysec,每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘;No,意味着不由 Redis 控制写回硬盘的时机,由操作系统决定何时将缓冲区内容写回硬盘。AOF 日志过大,会触发压缩机制 bgrewriteaofRDB 做快照时会阻塞线程吗?执行了 save 命令,就会在主线程生成 RDB 文件,由于和执行操作命令在同一个线程,会阻塞主线程;执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞;Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsave 命令save 900 1 //900 秒之内,对数据库进行了至少 1 次修改;save 300 10 //300 秒之内,对数据库进行了至少 10 次修改;save 60 10000 // 60 秒之内,对数据库进行了至少 10000 次修改。RDB 在执行快照的时候,数据能修改吗?可以的,执行 bgsave 过程中,Redis 依然可以继续处理操作命令的,也就是数据是能被修改的,关键的技术就在于多进程的写时复制技术(Copy-On-Write, COW)。为什么会有混合持久化?Redis 4.0 提出了混合持久化,既保证了 Redis 重启速度,又降低数据丢失风险。Redis 如何实现服务高可用?主从复制:一主多从的模式,且主从服务器之间采用的是「读写分离」的方式。哨兵模式:主从服务器出现故障宕机时,需要手动进行恢复。所以 Redis 增加了哨兵模式,因为哨兵模式做到了可以监控主从服务器,并且提供主从节点故障转移的功能。Redis Cluster: 分布式集群,采用哈希槽,来处理数据和节点之间的映射关系Redis 使用的过期删除策略是什么?Redis 使用的过期删除策略是「惰性删除 + 定期删除」这两种策略配和使用。惰性删除策略的做法是,不主动删除过期键,每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。定期删除策略的做法是,每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期 key。Redis 主从模式中,对过期键会如何处理?主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库Redis 内存满了,会发生什么?在 Redis 的运行内存达到了配置项设置的 maxmemory,就会触发内存淘汰机制Redis 内存淘汰策略有哪些?noeviction: 默认的内存淘汰策略,不淘汰任何数据,而是不再提供服务,直接返回错误。在设置了过期时间的数据中进行淘汰volatile-random:随机淘汰设置了过期时间的任意键值;volatile-ttl:优先淘汰更早过期的键值。volatile-lru:淘汰所有设置了过期时间的键值中,最久未使用的键值;volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;在所有数据范围内进行淘汰:allkeys-random:随机淘汰任意键值;allkeys-lru:淘汰整个键值中最久未使用的键值;allkeys-lfu:淘汰整个键值中最少使用的键值。如何避免缓存雪崩?将缓存失效时间随机打散,在原有的失效时间基础上增加一个随机值设置缓存不过期,通过业务逻辑来更新缓存数据如何避免缓存击穿互斥锁方案(Redis 中使用 SET EX NX)不给热点数据设置过期时间,由后台异步更新缓存如何避免缓存穿透判断求请求参数是否合理,请求参数是否含有非法值、请求字段是否存在,如果判断出是恶意请求就直接返回错误可以针对查询的数据,在缓存中设置一个空值或者默认值返回给应用,而不会继续查询数据库。使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在Redis 如何实现延迟队列?在 Redis 可以使用有序集合(ZSet)的方式来实现延迟消息队列的,ZSet 有一个 Score 属性可以用来存储延迟执行的时间。zadd score1 value1 命令就可以一直往内存中生产消息。 zrangebyscore 查询符合条件的所有待处理的任务, 通过循环执行队列任务即可。Redis 的大 key 如何处理?一般而言,下面这两种情况被称为大 key:String 类型的值大于 10 KB;Hash、List、Set、ZSet 类型的元素的个数超过 5000 个;//最好选择在从节点上执行该命令。因为主节点上执行时,会阻塞主节点,只能返回每种类型中最大的那个 bigkey,无法得到大小排在前 N 位的 bigkey,对于集合类型来说,只统计集合元素个数的多少,而不是实际占用的内存量。redis-cli -h 127.0.0.1 -p6379 -a "password" -- bigkeysscan命令,配合key类型再用对应的命令计算内存//使用 RdbTools 第三方开源工具,可以用来解析 Redis 快照(RDB)文件,找到其中的大 key。rdb dump.rdb -c memory --bytes 10240 -f redis.csv如何删除大 key?分批次删除异步删除(Redis 4.0 版本以上)推荐使用从 Redis 4.0 版本开始,可以采用异步删除法,用 unlink 命令代替 del 来删除。这样 Redis 会将这个 key 放入到一个异步线程中进行删除,这样不会阻塞主线程。我们还可以通过配置参数,达到某些条件的时候自动进行异步删除。Redis 管道有什么用?把多条命令拼接到一起,当成一次请求发出去,结果也是拼接到一起发回来,免去了每条命令执行后都要等待的情况,从而有效地提高了程序的执行效率。Redis 事务支持回滚吗?Redis 中并没有提供回滚机制如何用 Redis 实现分布式锁的?SET lock_key unique_value NX PX 10000 lock_key 就是 key 键;unique_value 是客户端生成的唯一的标识,区分来自不同客户端的锁操作;NX 代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;PX 10000 表示设置 lock_key 的过期时间为 10s,这是为了避免客户端发生异常而无法释放锁。解锁需要 Lua 脚本保证原子性// 释放锁时,先比较 unique_value 是否相等,避免锁的误释放if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])elsereturn 0end基于 Redis 实现分布式锁有什么缺点?超时时间不好设置。集群情况下的不可靠性。Redis 如何解决集群情况下分布式锁的可靠性?为了保证集群环境下分布式锁的可靠性,Redis 官方已经设计了一个分布式锁算法 Redlock(红锁)。它是基于多个 Redis 节点的分布式锁,官方推荐是至少部署 5 个 Redis 节点,而且都是主节点为什么用跳表而不用平衡树?从内存占用上来比较,跳表比平衡树更灵活一些。在做范围查找的时候,跳表比平衡树操作要简单从算法实现难度上来比较,跳表比平衡树要简单得多如何保证缓存和数据库数据的一致性?更新数据库 + 更新缓存如果我们的业务对缓存命中率有很高的要求,我们可以采用「更新数据库 + 更新缓存」的方案,但是在两个更新请求并发执行的时候,会出现数据不一致的问题所以我们得增加一些手段来解决这个问题,这里提供两种做法:在更新缓存前先加个分布式锁,保证同一时间只运行一个请求更新缓存,当然对于写入的性能就会带来影响。在更新完缓存时,给缓存加上较短的过期时间,缓存的数据也会很快过期,先删除缓存 + 更新数据库延迟双删删除缓存redis.delKey(X)更新数据库db.update(X)睡眠Thread.sleep(N)再删除缓存redis.delKey(X)
2023年08月12日
13 阅读
0 评论
0 点赞
2023-08-12
Composer命令全解析
Composer中文文档Composer命令全解析常用命令镜像配置中国镜像composer config -g repo.packagist composer https://packagist.phpcomposer.com配置其他厂商镜像阿里云 (好像说停用了)composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/腾讯composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/华为composer config -g repo.packagist composer https://repo.huaweicloud.com/repository/php/解除镜像composer config -g --unset repos.packagist项目搜索项目composer search ThinkPHP创建项目composer create-project topthink/ThinkPHP=5.1.* ./tp5安装扩展composer require laravel/laravel ">=5.5"移除扩展composer remove laravel/laravel生产最佳实践转换 PSR-0/4 autoloading 到 classmap 获得更快的载入速度,禁用开发者模式composer dump-autoload -o --no-dev 自动加载 autoload目前支持四种自动加载方式:PSR-0PSR-0 规范是 PHP5.2 之前的一种命名空间映射规范,它规定命名空间与文件路径的对应关系如下命名空间中的每个下划线字符(_)都会被转换成目录分隔符(/);命名空间中的每个命名空间分隔符(\)都会被转换成目录分隔符(/);命名空间中的首字母和下划线字符都会被转换成目录名和文件名中的小写字母;每个类的文件名必须与类名完全一致,包括大小写。"psr-0" : { "Foo\\" : "psr0src/", # "Foo_Bar_" : "psr0src/" },composer install/update 之后,PSR-0 引用全部合并到 vendor/composer/autoload_namespaces.phpPSR-4PSR-4 规范是较新的一种命名空间映射规范,它与 PSR-0 规范的区别在于:命名空间中的下划线字符不再被特殊处理,只有命名空间分隔符(\)会被转换成目录分隔符(/);命名空间中的首字母和下划线字符不再被强制转换成小写字母;类的文件名与类名可以不完全一致,但必须满足相对文件路径和类名的对应关系"psr-4": { #查找Afishpapa\Httptool\Http类时的路径为src/Http.php "Afishpapa\\Httptool\\": "src/" #可以在src/和lib/ 下面找 Monolog命名空间下的类 "psr-4": { "Monolog\\": ["src/", "lib/"] } #所有命名空间都来src/目录下找 "" : "src/" }composer install/update 之后,PSR-4 引用全部合并到 vendor/composer/automoad_psr4.php 中。return array( 'Afishpapa\\Httptool\\' => array($baseDir . '/src'), );Classmapcomposer install/update 之后,PSR-4 引用全部合并到 vendor/composer/autoload_classmap.php 中。你可以用 classmap 生成支持支持自定义加载的不遵循 PSR-0/4 规范的类库。Files通常作为函数库的载入方式(而非类库)。{ "autoload": { "files": ["src/MyLibrary/functions.php"] } }全局配置-v : 增加消息的详细程度,正常输出-vv : 增加消息的详细程度,更加详细得输出-vvv : 增加消息的详细程度,debug用-h : 显示帮助-q : 不要显示任何信息-n : 不要问任何交互问题-d : 设置工作目录--ansi: 强制输出 ANSI 编码--no-ansi: 禁用 ANSI 编码--version (-V): 展示所有应用版本--profile: 展示时间和内存信息常用配置--prefer-install: 默认值为distdist: 检查本地缓存压缩包,如果有直接复制到vendor目录,如果本地缓存没有,则去远程仓库下载压缩包,如果远程仓库没有提供压缩包,则尝试从github中安装包,并且删除.git版本信息,总之,dist能够快速地下载并安装依赖包,适用于大部分生产环境。 source: 直接从github中下载源码,保留.git信息,如果您需要对包进行自定义修改或者需要对其进行特殊的构建过程,则应该使用 source。 auto:2.1版本后已弃用-o: 生成自动加载器文件的优化版本,以加快类加载速度。-a: 默认情况下,Composer 会根据 composer.json 中的 PSR-4 和 PSR-0 配置来生成自动加载器, 使用 --classmap-authoritative 选项可以让 Composer 忽略 PSR-4 和 PSR-0 配置,而直接根据类文件生成一个类映射表(class map),并将其作为自动加载器的唯一来源。需要注意的是,使用 --classmap-authoritative 选项可能会导致一些问题,比如在添加新的类文件时需要重新生成类映射表,否则新添加的类无法被自动加载器加载。因此,建议在开发环境中使用这个选项来提高性能,但在生产环境中不要使用,以免出现问题。--dry-run: 执行安装过程的模拟运行,不会实际下载或安装任何软件包。--dev: 安装开发依赖项,包括测试框架和调试工具等。composer init以交互方式初始化 composer--name: 包名,格式为作者/名称,比如monolog/monolog--description: 简短描述--author: 作者名--type: 包的安装类型,默认librarylibrary : 它会简单的将文件复制到 vendor 目录 project : 当前包是一个项目,而不是一个库 metapackage : 一个空的包,包含依赖并且需要触发依赖的安装,这将不会对系统写入额外的文件。 composer-plugin : 它有一个自定义安装类型,可以为其它包提供一个 installler。--homepage: 官网首页--require: 引入包,格式为 包:版本 foo/bar:1.0.0--require-dev: 开发用的组件-s : 最小稳定性值 dev stable --license (-l): 许可证--repository: 指定一个或多个 Composer 仓库-a : 添加一个autoload.psr-4的对象到composer.jsoncomposer install如果存在 composer.lock 文件,它会从此文件读取依赖版本,这确保了该库的每个使用者都能得到相同的依赖版本。如果不存在 composer.lock 文件,它会从 composer.json 文件读取依赖版本,并把其安装到 vendor 目录下。如果没有 composer.lock 文件,composer 将在处理完依赖关系后创建它。composer require添加一个包到 composer.json 文件,如果没有 composer.json 就创建一个# 该命令会安装两个不同的软件包 # vendor/package:2.* : 版本号以 2. 开头,后面跟着任何版本号。 # vendor/package2:dev-master : 使用 dev-master 分支。这意味着它将安装该分支的最新版本,通常是开发版本,不属于正式发布。 composer require "vendor/package:2.*" vendor/package2:dev-mastercomposer update获取依赖的最新版本# 只更新这两个包vendor/package vendor/package2 composer update vendor/package vendor/package2 # 更新符合正则匹配的包 composer update "vendor/*" # 更新依赖包到指定版本,需符合composer.json的约束 composer update --with vendor/package:2.0.1composer remove移除依赖包# 移除这两个包 composer remove vendor/package vendor/package2 composer reinstall 重装包,如果不小心改了包文件,可以使用重装命令恢复 # 重装两个包 composer reinstall acme/foo acme/bar # 重装正则匹配的包 composer.phar reinstall "acme/*"composer check-platform-reqs用于检查您的 PHP 和扩展版本是否符合已安装包的平台要求--lock: 仅从锁定文件中检查要求,而不是从已安装的包中检查要求。 --no-dev: 不检查 require-dev 包要求。 -f: 格式> composer check-platform-reqs Checking platform requirements for packages in the vendor dir ext-json 1.7.0 success ext-libxml 7.3.4 success ext-mbstring 7.3.4 success ext-openssl 7.3.4 success ext-simplexml 7.3.4 success php 7.3.4 successcomposer globalglobal 允许您全局运行其他命令,如 install、remove、require,updatecomposer search monolog搜索依赖包-N : 只搜包名-O : 只搜作者-t : 搜全称λ composer search monolog monolog/monolog Sends your logs to files, sockets, inboxes, databases and various web services symfony/monolog-bundle Symfony MonologBundle symfony/monolog-bridge Provides integration for Monolog with various Symfony components ...composer show / composer info列出所有可用的包信息λ composer show defuse/php-encryption v2.3.1 Secure PHP Encryption Library laminas/laminas-diactoros 2.5.0 PSR HTTP Message implementations laminas/laminas-zendframework-bridge 1.4.1 Alias legacy ZF class names to Laminas Project equivalents. ...列出单个包的详情λ composer show slim/slim name : slim/slim descrip. : Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs keywords : api, framework, micro, router versions : * 3.12.4 type : library license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText homepage : https://slimframework.com source : [git] https://github.com/slimphp/Slim.git ce3cb65a06325fc9fe3d0223f2ae23113a767304 dist : [zip] https://api.github.com/repos/slimphp/Slim/zipball/ce3cb65a06325fc9fe3d0223f2ae23113a767304 ce3cb65a06325fc9fe3d0223f2ae23113a767304 path : D:\workspace\oauth\examples\vendor\slim\slim names : slim/slim, psr/http-message-implementation support issues : https://github.com/slimphp/Slim/issues source : https://github.com/slimphp/Slim/tree/3.12.4 autoload psr-4 Slim\ => Slim requires ext-json * ext-libxml * ext-simplexml * nikic/fast-route ^1.0 php >=5.5.0 pimple/pimple ^3.0 psr/container ^1.0 psr/http-message ^1.0 requires (dev) phpunit/phpunit ^4.0 squizlabs/php_codesniffer ^3.6.0 provides psr/http-message-implementation 1.0composer outdated列出所有安装包是否可以更新λ composer outdated Direct dependencies required in composer.json: laminas/laminas-diactoros 2.5.0 2.14.0 PSR HTTP Message implementations league/event 2.2.0 3.0.1 Event package slim/slim 3.12.4 4.9.0 Slim is a PHP micro framework that helps you quickly write simple yet po... Transitive dependencies not required in composer.json: psr/container 1.1.1 2.0.1 Common Container Interface (PHP FIG PSR-11)composer browse / composer home浏览器直接打开这个包的 github 仓库# 打开这个包的官网 composer browser -H slim/slim # 打印slim的github仓库链接 composer browser -s slim/slimcomposer suggests给你人生路上一点建议λ composer suggests lcobucci/jwt suggests: - lcobucci/clock: * 1 additional suggestions by transitive dependencies can be shown with --all composer fund给出你所用的包的捐赠链接composer depends / whycomposer depends 命令用于显示一个包的依赖关系树。如果你要删除一个包之前,可以用这个命令先看看它上面是不是有人> composer depends psr/log -t psr/log 1.1.4 Common interface for logging libraries ├──composer/composer 2.4.x-dev (requires psr/log ^1.0 || ^2.0 || ^3.0) ├──composer/composer dev-main (requires psr/log ^1.0 || ^2.0 || ^3.0) ├──composer/xdebug-handler 3.0.3 (requires psr/log ^1 || ^2 || ^3) │ ├──composer/composer 2.4.x-dev (requires composer/xdebug-handler ^2.0.2 || ^3.0.3) │ └──composer/composer dev-main (requires composer/xdebug-handler ^2.0.2 || ^3.0.3) └──symfony/console v5.4.11 (conflicts psr/log >=3) (circular dependency aborted here)composer prohibits / why-not告诉您哪些包在阻止你想安装的包,并给出理由composer validate如果你手动修改 composer.json, 当准备提交 composer.json 文件之前,最好执行这条命令检查一下composer status如果你手动修改过一个包,这个包安装来源是 source, 则可以用这个命令看你本地修改记录,相当于 git statuscomposer self-update / selfupdatecomposer 程序自更新# 更新到指定版本 composer self-update 2.4.0-RC1composer config修改当前项目或者全局的配置-g : 修改全局配置文件--unset: 移除配置-l: 展示全部配置信息,如果加上-g,就显示全局的--absolute: *-dir的配置返回绝对路径--append: 追加一个镜像时,设置比较低的优先级--source: 展示config从哪里加载的# 添加一个测试foo到repositories composer config repo.foo vcs https://github.com/foo/bar # 添加一个阿里云镜像到repositories(阿里云镜像凉了) composer config repo.packagist composer https://mirrors.aliyun.com/composer/ #效果如下 "repositories": { "packagist": { "type": "composer", "url": "https://mirrors.aliyun.com/composer/" }, "foo": { "type": "vcs", "url": "https://github.com/foo/bar" } } # 修改extra配置 composer config extra.foo.bar value composer config --json extra.foo.bar '{"baz": true, "qux": []}'composer create-project创建项目 / 包,相当于 git clone + composer installcomposer create-project doctrine/orm path "2.2.*"composer dump-autoload当修改了包里面的类名,或者增加删除文件之后,需要执行这个命令# -o 选项是为了生产环境中的性能优化, composer dump-autoload -o # -a 选项则是为了开发环境中的重新生成类映射。 composer dump-autoload -acomposer clear-cache / clearcache / cc清理本地包缓存archive从远程下载一个包,并打包成 zip/tar 压缩包php composer.phar archive vendor/package 2.0.21 --format=ziprun-script / run你可以运行此命令来手动执行,只需要指定脚本的名称,可选的 --no-dev 参数允许你禁用开发者模式。{ "scripts": { "post-update-cmd": "MyVendor\\MyClass::postUpdate", "post-package-install": [ "MyVendor\\MyClass::postPackageInstall" ], "post-install-cmd": [ "MyVendor\\MyClass::warmCache", "phpunit -c app/" ] } } # 将会运行所有 post-install-cmd 事件下定义的脚本。 `composer run-script post-install-cmd` diagnose可以用来检查当前 Composer 环境是否符合最佳实践,包括 PHP 环境、Composer 配置等。audit检查当前项目的依赖项是否存在已知的安全漏洞。help使用 help 可以获取指定命令的帮助信息。php composer.phar help install
2023年08月12日
20 阅读
0 评论
0 点赞
2023-08-12
Hyperf 3.0
Hyperf 3.0回顾在过去的一年半时间里,Hyperf 2.2 共发布了 35 个小版本,使 Hyperf 达到了一个前所未有的高度,这里也获得了一些不错的数据反馈。Hyperf 在 GitHub 和 Gitee 上的关注度也得到了显著提升,分别获得了 4.9k 和 791 个 star,整体关注度增长也很稳定。Hyperf 框架的安装量也达到了 90万次,每天都有约 1300次的安装,这也表明了 Hyperf 已经广泛应用于相关行业中并支撑了大量的系统运行。Hyperf 组织下的有效 repo 更是达到了约 140个(去除掉 Archive 项目后),维护工作量空前巨大,但迭代仍然高频。感谢 Hyperf 团队全体成员的辛勤以及贡献,同时也感谢所有的 PR 贡献者,没有你们的参与也就没有今天的 Hyperf。Thanks ALL ContributorsHyperf 3.0 新时代Hyperf 3.0 带来了很多非常有意思的新能力,其中一些新能力不乏是 PHP 领域里面前所未有的,当然这些新能力也脱离不了其他开源社区的积极发展,包括但不限于 PHP、Swoole、Swow、PHPMicro、DTM、Seata 等开源社区,也衷心希望大家在闲暇时间可以为这些开源社区也贡献出自己的一份力,搭上一砖一瓦,共建更加美好的未来。原生注解 (Attribute)随着 PHP 8.1、8.2 的发布,给 PHP 带来了很多新的特性,其中与 Hyperf 最为相关的就是 PHP 的原生注解(Attribute) 了,Hyperf 3.0 也放弃了过往采用的基于注释解析的注解功能实现,转而采用 PHP 的原生注解,当然对应依赖的 PHP 版本,也将调整为最低要求 PHP 8.0。我们以一个最简单的 Controller 案例来呈现新的原生注解的使用:<?phpdeclare(strict_types=1);namespace App\Controller;use Hyperf\HttpServer\Contract\RequestInterface;use Hyperf\HttpServer\Annotation\Controller;use Hyperf\HttpServer\Annotation\RequestMapping;[Controller]class IndexController{// Hyperf 会自动为此方法生成一个 /index/index 的路由,允许通过 GET 或 POST 方式请求 #[RequestMapping(path: "index", methods: "get,post")] public function index(RequestInterface $request) { // 从请求中获得 id 参数 $id = $request->input('id', 1); return (string)$id; }}同时随着原生注解的应用,在 3.0 中也能够支持在同一个位置重复应用同一个注解了,比如过往在一个 Controller Action 想要应用多个 Middleware 时,需要通过 @Middlewares 注解包含多个 @Middleware 注解实现应用,而在 3.0 则可直接书写多个 @Middleware 注解实现该应用。同时在 3.0 中,注解也可以应用在方法的参数上,以实现一些针对方法参数定义、参数解析等功能。从 注释注解 调整为 原生注解,也无需担忧过往项目的迁移改造工作量,Hyperf 也提供了对应的工具一键自动转换,只需要在 2.2 时引入 hyperf/code-generator 组件,并执行 php bin/hyperf.php code:generate -D app 命令,即可将 app 文件夹内的注释注解自动转为原生注解,轻松省力~分布式事务在过去的一年里,Hyperf 团队也为 PHP 领域孵化了两个前所未有的分布式事务组件并贡献到对应的开源社区,对应 DTM (首个基于 Go 语言实现的流行分布式事务管理器) 与 Seata (由阿里巴巴开源的流行分布式事务管理器) 两款主流的开源分布式事务管理器,分别是 dtm-php/dtm-client 和 seata/seata-php ,其中 dtm-php 是实现了 dtm 完整功能的分布式事务客户端,已支持 TCC模式、Saga、XA、二阶段消息模式的分布式事务模式,并分别实现了与 DTM Server 以 HTTP 协议 或 gRPC 协议 通讯,该客户端可安全运行于 PHP-FPM 和 Swoole 协程环境中,更是对 Hyperf 框架做了更加易用的功能支持,可应用于生产环境中,而 seata-php 仍在开发迭代中,尚未能用于生产环境,也希望能有更多人参与进来共同迭代。我们也以一个简单的例子来说明如何在 Hyperf 中实现一个 TCC 分布式事务的调用,其它分布式事务模式可查阅 dtm-php repo 的 README 文件,或 Hyperf 3.0 文档关于分布式事务一章。<?phpnamespace App\Controller;use DtmClient\TCC;use DtmClient\TransContext;use Hyperf\Di\Annotation\Inject;use Hyperf\HttpServer\Annotation\Controller;use Hyperf\HttpServer\Annotation\GetMapping;use Throwable;[Controller(prefix: '/tcc')]class TccController{protected string $serviceUri = 'http://127.0.0.1:9501'; #[Inject] protected TCC $tcc; #[GetMapping(path: 'successCase')] public function successCase() { try { $this->tcc->globalTransaction(function (TCC $tcc) { // 创建子事务 A 的调用数据 $tcc->callBranch( // 调用 Try 方法的参数 ['amount' => 30], // Try 方法的 URL $this->serviceUri . '/tcc/transA/try', // Confirm 方法的 URL $this->serviceUri . '/tcc/transA/confirm', // Cancel 方法的 URL $this->serviceUri . '/tcc/transA/cancel' ); // 创建子事务 B 的调用数据,以此类推 $tcc->callBranch( ['amount' => 30], $this->serviceUri . '/tcc/transB/try', $this->serviceUri . '/tcc/transB/confirm', $this->serviceUri . '/tcc/transB/cancel' ); }); } catch (Throwable $e) { var_dump($e->getMessage(), $e->getTraceAsString()); } // 通过 TransContext::getGid() 获得 全局事务ID 并返回 return TransContext::getGid(); } }至于其它事务模式,如 Saga、XA、二阶段消息模式等,可以具体查阅 dtm-php/dtm-client 仓库的 Readme 文件或 Hyperf 3.0 的相关文档。Swow 网络引擎实际上在 Hyperf 2.2 中,就已经支持了 Swow 网络引擎的运行,随着 Swow 1.0 正式版的发布,在 Hyperf 3.0 中,我们也把 Swow 的应用提高到了一个更高的高度,Swow 实现了一套有史以来最完整的 PHP 协程模型,它全面释放了 PHP 的真正实力,使得开发者可以做到以往难以想象的事情,对比 Swoole 它具备更好的兼容性、可调试性、可编程性,它甚至能使 Hyperf 运行于原生 Windows 环境下而无需借助 WSL 或 Docker,同时也提供了 SDB 和 Watchdog 工具对协程运行进行调试和监控,极大的提升了 Hyperf 的可调试性。我们提供了一个全新的 Skeleton 骨架项目用于快速创建一个基于 Swow 网络引擎的 Hyperf 应用,以下是一个简单的通过 Composer 创建应用的流程:composer create-project hyperf/swow-skeleton:dev-master 创建后,确保您的 PHP 环境已经安装好了 Swow 扩展,便可直接通过 php bin/hyperf.php start 命令启动服务,整体使用与原来无异,Hyperf 底层已做好了适配。在 Windows 环境中也只需在 CMD 或者 Poweshell 中运行即可哦~SDB 协程调试器SDB 是一款使用 PHP 语言编写的协程调试器工具,使用上类似于 GDB,它具有以下的几个优点:使用简单,只需要一行代码即可开启;无需端口,可直接运行在 TTY 上;零成本,可在生产环境使用,不影响性能;功能强大,深度定制,量身打造类微型操作系统;通过 SDB,您可以对运行中的 Hyperf 应用进行交互,以实现查看当前所有协程状态、窥视协程、进入指定协程、查看调用栈、打断点、单步调试、查看及修改变量调试、扫描僵尸协程、Kill 协程等操作,真正意义上的将 PHP 协程带到了工程化的实用阶段。WatchdogWatchdog 为 PHP 提供了 CPU 调度能力,其核心原理是 Watchdog 线程会定期检查其它线程中协程的活跃度情况,若发现工作线程中的协程不再活跃,则通过 ZendVM 的中断机制对其进行状态确认,若 VM 中断失败,则表明工作线程陷入了系统调用阻塞,触发告警;若 VM 中断成功,则表明工作线程陷入了 CPU 密集运算或死循环,则立即触发用户设定的调度规则进行调度。通过 Watchdog 可以实现 可编程的协程调度机制,可以非常方便的解决过往头疼的 CPU 饥饿 问题,以下是一些用法的演示:// 运行超过 1ms 就让出控制权\Swow\WatchDog::run(1 1000 1000);// 运行超过 1ms 就让出 10ms,调度失败并超过 5ms 时视为系统调用阻塞\Swow\WatchDog::run(1 1000 1000, 5 1000 1000, 10);// 可编程方式,函数会在程序阻塞 100ms 后触发$alertCountMap = new WeakMap();\Swow\WatchDog::run(quantum: 100 1000 1000, alerter: static function () use ($alertCountMap): void {$coroutine = Coroutine::getCurrent(); $alertCount = ($alertCountMap[$coroutine] ??= 0) + 1; $alertCountMap[$coroutine] = $alertCount; echo 'CPU starvation occurred, suspend this coroutine...' . PHP_EOL; sleep(0); if ($alertCount > 5) { echo 'Kill the bad guy' . PHP_EOL; $coroutine->kill(); }});更多用法关于 SDB 和 WatchDog 以及更多用法目前文档可能尚未完善,我们接下来也会编写多篇文章来阐述用法,也会尽快完善相关文档~BoxBox 是一个致力于帮助提升 PHP 应用程序的编程体验的工具,尤其有助于 Hyperf 应用,可以用于管理 PHP 环境和相关依赖,同时提供将 PHP 应用程序打包为二进制程序的能力,还提供反向代理服务来管理和部署 Swoole/Swow 服务。这些能力也是前所未有的,特别是将 Hyperf 或 PHP 应用打包为二进制程序的能力,打包好的程序,可以不依赖系统的 PHP 环境单独运行,以达到类似于 Go 语言的打包能力,这些能力也得益于 phpmicro 的发展,而 Box 则是站在巨人的肩膀上,将这些能力以更加简单易用的方式提供给大家使用~以下是一个通过下载 Box 到创建一个 Hyperf 应用,并运行的简单案例:安装 Box// Macwget https://github.com/hyperf/box/releases/download/v0.5.5/box_x86_64_macos -O boxsudo mv ./box /usr/local/bin/boxsudo chmod 755 /usr/local/bin/box// 确保 /usr/local/bin/box 在你的 $PATH 环境中,或者将 box 放到你想要的任意 $PATH 路径中// Linux x86_64wget https://github.com/hyperf/box/releases/download/v0.5.5/box_x86_64_linux -O boxsudo mv ./box /usr/local/bin/boxsudo chmod 755 /usr/local/bin/box// 确保 /usr/local/bin/box 在你的 $PATH 环境中,或者将 box 放到你想要的任意 $PATH 路径中// Windowscurl -o box.exe https://github.com/hyperf/box/releases/download/v0.5.5/box_x64_windows.exe// 将 box.exe 放到你想要的任意 Path 环境变量路径中,同时 Windows 版本在执行时需要在命令行中使用 box.exe 而不是 box初始化 Github Access TokenBox 需要一个 Github 访问令牌来请求 Github API,以便于从 GitHub Actions 的 Artifacts 中检索包的版本。创建 Github Access Token,workflow 范围需要勾选;运行 box config set github.access-token 命令来设置您的 token;我们将在 v0.6 版本让使用 Box 前无需设置 Github Access Token,以提供更加简便的使用体验,请期待~通过 Box 初始化 PHP 环境并启动 Hyperf// 通过 box 安装 PHP 8.1,此安装不会影响系统原来自身安装的 PHPbox get php@8.1// 通过 box 安装 composerbox get composer// 通过 box composer 创建 hyperf 应用,可指定 dev-master 分支以防止 packagist 代理数据落后的问题box composer create-project hyperf/swow-skeleton:dev-master// 通过 box 启动 hyperfbox hyperf start至此一个完整的安装和运行流程已完成,我们可以发现过往复杂的环境部署环节,已经简化为了区区几个命令,通过 && 连接符甚至可以组成一行命令足以。通过 Box 打包 Hyperf 应用为二进制程序这个神奇的能力,在操作上也被简化得匪夷所思,只需预先执行 box build-prepare 命令提前下载好相关依赖,这个命令只需执行一次即可,后续即可通过 box build 命令对当前所在文件夹的 Hyperf 应用进行打包动作。打包好后,当前文件夹会出现一个名为 hyperf 的二进制文件,后续只需要通过 hyperf start 命令即可启动该 Hyperf 应用。Box 自身就是一个基于 Box 打包出来的 Hyperf 应用,大家也可以通过了解 Box 项目本身,来了解该能力的使用。Box Kernel 切换默认情况下,Box 由 Swow Kernel 提供支持,但是我们也提供了 Swoole Kernel,您可以通过 box config set kernel swoole 来切换为 Swoole Kernel,但是需要注意的是,Swoole Kernel 仅支持 PHP 8.1 版本,且不支持构建二进制程序功能和 Windows 系统环境。// 设置为 Swow Kernel [默认]box config set kernel swow// 设置为 Swoole Kernel (不支持 Windows)box config set kernel swooleBox 的更多能力Box 还有更多有意思的使用方法和工具组合,可以通过下面的部分的命令清单快速一览命令box get pkg@version从远程安装包,pkg是包名,version是包的版本,box get pkg表示安装最新版本的 pkg,例如, 运行 box get php@8.1 安装 PHP 8.1, 运行 box get composer 安装最新的 composer binbox build-prepare 为 build 和 build-self 命令做好相关环境的准备box build-self 构建 box bin 本身box build 将 Hyperf 应用程序构建成二进制文件box self-update 将 box bin 更新至最新版本box config set-php-version 设置 box 的当前 PHP 版本,可用值:8.0 | 8.1box config get-php-version 获取 box 的当前设置的 PHP 版本box reverse-proxy -u <upsteamHost:upstreamPort> 启动一个反向代理 HTTP 服务器,用于将 HTTP 请求转发到指定的多个上游服务器box php 通过当前 box 的 PHP 版本运行任何 PHP 命令box composer 通过当前 box 的 PHP 版本运行任何 Composer 命令box php-cs-fixer 通过当前 box 的 PHP 版本运行任何 php-cs-fixer 命令box cs-fix 通过当前 box 的 PHP 版本运行 php-cs-fixer fix 命令box phpstan 通过当前 box 的 PHP 版本运行任何 phpstan 命令box pint 通过当前 box 的 PHP 版本运行任何 pint 命令更多优化Hyperf 3.0 仍做了大量的优化和调整,具体可以阅读 Hyperf 主仓库中的 CHANGELOG-3.0.md 文件。同时我们也为大家准备了一份从 2.2 升级至 3.0 的指南,具体可查阅 Hyperf 官方文档 - 3.0 升级指南 一章。相关链接Hyperf 的详细介绍:点击查看Hyperf 的下载地址:点击下载
2023年08月12日
15 阅读
0 评论
0 点赞
1
...
78
79
80
...
157