PHP代码洁癖心得
if的使用洁癖 给定初始值 123456789101112if ($orderStatus == 1) { $orderDesc = '已支付';# 其他的elseif ...} else { $orderDesc = '未支付';}// 优化后$orderDesc = '未支付';if ($orderStatus == 1) { $orderDesc = '已支付';} 简单的判断使用&&代替 123456if (strlen($newPwd) < 6) { $message = '密码长度不足!';}// 优化后strlen($newPwd) < 6 && $message = '密码长度不足!'; 三元运算符 12345678if (empty($_POST['action...
索引失效的 12 种原因
一句话 索引失效 = MySQL 优化器决定不用你建的索引去执行。 永远用 EXPLAIN 验证,不要靠记忆。 12 种失效场景1. WHERE 列上做函数 / 表达式1234567-- ❌ 索引失效SELECT * FROM users WHERE YEAR(created_at) = 2024;SELECT * FROM users WHERE id + 1 = 100;-- ✅ 改写:把函数挪到右边SELECT * FROM users WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';SELECT * FROM users WHERE id = 99; MySQL 8.0+ 支持 函数索引:ALTER TABLE users ADD INDEX idx_year ((YEAR(created_at))) 2. 隐式类型转换123456-- 字段是 VARCHAR,传了 INT-- ❌ 走全表扫SELECT * FROM...
覆盖索引(Covering Index)
一句话 覆盖索引 = 一个 SELECT 需要的所有字段,都能从二级索引里直接拿到,不需要回表。 EXPLAIN 显示 Using index 就是覆盖了。 一、为什么需要覆盖InnoDB 的二级索引存的是 主键值,不是数据行: 123456SELECT name FROM users WHERE age = 25;-- 走 idx_age 二级索引-- → 拿到主键 id 列表-- → 用 id 回到聚簇索引取整行 ← 这一步叫"回表"-- → 取出 name 回表 = 一次随机 IO。如果二级索引里直接就有 name,就省了这一步。 二、用联合索引覆盖12345678-- ❌ 普通索引,需要回表ALTER TABLE users ADD INDEX idx_age (age);SELECT name FROM users WHERE age = 25;-- ✅ 覆盖索引,name 直接在索引里ALTER TABLE users ADD INDEX idx_age_name (age, name);SELECT name FROM u...
索引的优缺点
一句话 索引以”读快、写慢、占空间”为代价换查询性能。 加索引前先想:这字段查得多吗?选择性够不够? 一、优点 优点 说明 加速 WHERE 查询 从 O(N) 全表扫描 → O(log N) B+ 树查找 加速 ORDER BY / GROUP BY 索引天然有序,省去 filesort 加速 JOIN 关联字段有索引时大幅提速 唯一索引保证唯一性 数据约束 + 查询双重价值 覆盖索引免回表 二级索引就能返回所有需要的列 二、缺点 缺点 说明 量化 占空间 每个索引都是一棵 B+ 树 一个 INT 索引在 100w 行表上约 30MB 写入变慢 INSERT/UPDATE/DELETE 都要维护所有相关索引 每多一个索引,写入慢 5-15% 优化器选错索引 索引太多反而干扰优化器 用 FORCE INDEX 兜底 维护成本 在线加索引要锁表/影响性能 大表用 pt-online-schema-change 三、加索引的判断标准✅ 该加: WHERE / ORDER BY...
MySQL 数据类型选型
一句话 选最小的、能装下你数据的类型。 类型小 = 索引小 = 内存命中率高 = 快。 一、整数类型 类型 字节 范围(无符号) 用途 TINYINT 1 0 ~ 255 状态枚举、布尔 SMALLINT 2 0 ~ 65535 较小计数 MEDIUMINT 3 0 ~ 1677w 较少用 INT 4 0 ~ 42亿 大多数主键、ID BIGINT 8 0 ~ 1844亿亿 雪花 ID、大表主键 1234-- ❌ 用户性别用 INTgender INT-- ✅ 用 TINYINTgender TINYINT UNSIGNED COMMENT '0未知 1男 2女' INT(11) 里的 11 不是长度!只是显示宽度(已废弃),实际仍是 4 字节。 二、字符串类型 类型 长度 适用 CHAR(n) 固定 n 字符 MD5、UUID、固定位手机号 VARCHAR(n) 可变 ≤ n 大多数字符串 TEXT (4 种) 长文本 文章正文,不要建普通索引 ENUM 枚举 不推荐,...
穿透&雪崩&击穿
雪崩 穿透 击穿 概念 当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死。 访问redis中一个不存在的key的时候,会直接穿过缓存,去数据库中进行查询。 场景 就是每秒有5000个请求过来时候,redis缓存库崩了,然后这些请求瞬间落在了mysql数据库上,直接导致数据库死机. 如果是黑客,进行恶意攻击的时候,每次都请求超过2000个/秒的时候,这个时候mysql基本上就挂了. 解决方案 事前:提高缓存库的高可用, 使用主从结构加哨兵 cluster集群事中:使用ehcache+hystrix限流组件(当请求量非常巨大的时候,就调用自己开发好的一个降级饿组件,返回一些默认值,如友情提示,或者空白值)事后:做持久化,尽快恢复缓存集群,一旦恢复,自动从磁盘上读取数据,恢复内存中的数据. 每次从数据库中查询到一个不存在的key的时候,就写一个空值到缓存库中,有恶意攻击的时候,直接从缓存...
Redis缓存穿透
我们使用Redis大部分情况都是通过Key查询对应的值,假如发送的请求传进来的key是不存在Redis中的,那么就查不到缓存,查不到缓存就会去数据库查询。假如有大量这样的请求,这些请求像“穿透”了缓存一样直接打在数据库上,这种现象就叫做缓存穿透。 分析: 关键在于在Redis查不到key值,这和缓存击穿有根本的区别,区别在于缓存穿透的情况是传进来的key在Redis中是不存在的。假如有黑客传进大量的不存在的key,那么大量的请求打在数据库上是很致命的问题,所以在日常开发中要对参数做好校验,一些非法的参数,不可能存在的key就直接返回错误提示,要对调用方保持这种“不信任”的心态。 解决方案: 1、把无效的Key存进Redis中。如果Redis查不到数据,数据库也查不到,我们把这个Key值保存进Redis,设置value=”null”,当下次再通过这个Key查询时就不需要再查询数据库。这种处理方式肯定是有问题的,假如传进来的这个不存在的Key值每次都是随机的,那存进Redis也没有意义。 2、使用布隆过滤器。布隆过滤器的作用是某个 key 不存在,那么就一定不存在,它说某...
Redis缓存雪崩
当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死。这就是缓存雪崩。 分析: 造成缓存雪崩的关键在于在同一时间大规模的key失效。为什么会出现这个问题呢,有几种可能,第一种可能是Redis宕机,第二种可能是采用了相同的过期时间。搞清楚原因之后,那么有什么解决方案呢? 解决方案: 1、在原有的失效时间上加上一个随机值,比如1-5分钟随机。这样就避免了因为采用相同的过期时间导致的缓存雪崩。 如果真的发生了缓存雪崩,有没有什么兜底的措施? 2、使用熔断机制。当流量到达一定的阈值时,就直接返回“系统拥挤”之类的提示,防止过多的请求打在数据库上。至少能保证一部分用户是可以正常使用,其他用户多刷新几次也能得到结果。 3、提高数据库的容灾能力,可以使用分库分表,读写分离的策略。 4、为了防止Redis宕机导致缓存雪崩的问题,可以搭建Redis集群,提高Redis的容灾性。
Socket
Socket是为了实现通信过程而建立成来的通信管道,其真实的代表是客户端和服务器端的一个通信进程,双方进程通过Socket进行通信,而通信的规则采用指定的协议。Socket只是一种连接模式,不是协议,TCP、UDP,简单的说(虽然不准确)是两个最基本的协议,很多其它协议都是基于这两个协议如,HTTP就是基于TCP的,.用Socket可以创建TCP连接,也可以创建UDP连接,这意味着,用Socket可以创建任何协议的连接,因为其它协议都是基于此的。 实际上,传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket本身不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的接口。
HTTP
什么是HTTP? 超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。 HTTP特点: 无状态:协议对客户端没有状态存储,对事物处理没有“记忆”能力,比如访问一个网站需要反复进行登录操作。 无连接:HTTP/1.1之前,由于无状态特点,每次请求需要通过TCP三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。 基于请求和响应:基本的特性,由客户端发起请求,服务端响应。 简单快速、灵活。 通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性。 HTTP报文组成: 请求行:包括请求方法、URL、协议/版本 请求头(Request Header) 请求正文 状态行 响应头 响应正文 HTTP的缺点: 通信使用明文(不加密),内容可...





