MySQL 8.0是MySQL的一个重大版本更新于2018年4月正式发布带来了很多令人兴奋的新特性和,改进特别是在性能高可用高并发安全等方面有很大的提升被认为是MySQL历史上最好的一个版本。
最近我们团队把数据库从MySQL 5.7升级到了MySQL 8.0并且重新设计了数据库架构实现了高可用和高并发踩了不少坑也积累了一些经验今天想分享一下MySQL 8.0的重要新特性以及,基于MySQL 8.0的高可用高并发架构设计实践包括主从复制读写分离分库分表连接池优化等等希望能帮大家更好地使用MySQL 8.0。
一、MySQL 8.0的重要新特性
先说说MySQL 8.0的重要新特性这些新特性是我们升级到8.0的重要原因也是架构设计的基础。
1. 性能大幅提升:
MySQL 8.0在性能方面有很大的提升特别是在高并发场景下性能提升明显官方数据显示MySQL 8.0在,读写密集型工作负载下比MySQL 5.7快2倍在只读工作负载下快4倍这主要得益于以下改进:
- InnoDB性能提升:InnoDB存储引擎在8.0有很多性能改进,比如更快的自动增量缓冲重构了缓冲池刷新机制优化了MVCC(多版本并发控制)减少了锁竞争等等。
- 更快的连接和认证:8.0重构了连接和认证过程支持更快的建立连接特别是,在大量连接的场景下性能提升明显。
- 优化器改进:8.0的查询优化器有很大改进支持更好的查询计划选择特别是对于复杂查询和,子查询优化更好性能更稳定。
- 窗口函数:8.0新增了窗口函数(Window Function)能更高效地处理一些复杂的分析查询,比如排名累计求和移动平均等等以前需要用复杂的子查询,或者变量来实现现在用窗口函数几行就搞定性能也更好。
2. 高可用改进:
MySQL 8.0在高可用方面也有很大的改进特别是InnoDB Cluster的成熟和,Group Replication的改进让MySQL的高可用方案更简单更可靠。
- InnoDB Cluster:8.0正式推出了InnoDB Cluster这是一个完整的高可用解决方案包括Group Replication(组复制)MySQL Router(路由)和MySQL Shell(管理工具)能轻松搭建一个高可用的MySQL集群支持自动故障转移自动重新配置非常方便以前搭建MySQL高可用需要用MHAKeepalived等第三方工具比较复杂现在用InnoDB Cluster原生就支持简单很多。
- Group Replication改进:8.0的Group Replication(组复制)有很多改进支持单主模式和,多主模式支持自动选举新主自动故障转移数据一致性也更好比传统的主从复制更可靠更高可用。
- 更好的复制:8.0的主从复制也有改进支持更快的复制性能更好的数据一致性更灵活的复制过滤等等特别是,GTID(全局事务ID)的改进让复制更可靠更好维护。
3. 安全增强:
MySQL 8.0在安全方面也有很大的增强默认就更安全也支持更多的安全特性。
- 默认使用cachingsha2password认证插件:8.0默认使用cachingsha2password认证插件代替了以前的mysqlnativepassword安全性更高支持更强的密码加密和认证。
- 角色(Role)支持:8.0新增了角色(Role)功能可以把一组权限赋给一个角色,然后把角色赋给用户这样权限管理更方便更灵活特别是用户多的场景很实用。
- 更细粒度的权限控制:8.0支持更细粒度的权限控制,比如可以限制用户只能访问某些表的某些列支持资源限制(限制用户的查询次数连接次数等等)更安全也更公平。
- 数据加密:8.0支持更强的数据加密包括静态数据加密(InnoDB Tablespace Encryption)传输加密(SSL/TLS)等等保护数据安全。
4. 其他重要新特性:
除了上面的几个方面MySQL 8.0还有很多其他重要新特性:
- CTE(公共表表达式):支持WITH子句能写更复杂更清晰的查询特别是,递归CTE能处理树形结构等复杂查询。
- 降序索引:8.0真正支持降序索引(以前,虽然语法支持,但是实际是升序存储反向扫描)性能更好特别是ORDER BY ... DESC的查询提升明显。
- JSON功能增强:8.0的JSON功能更强大支持更多的JSON函数操作更方便性能也更好。
- 更好的地理空间支持:8.0重构了地理空间支持支持更多的空间参考系统(SRS)更准确的空间计算适合地理位置相关的应用。
- 数据字典升级:8.0用InnoDB数据字典代替了以前的元数据文件(.frm等等)数据字典更可靠更好维护事务性也更好。
二、高可用架构设计
了解了MySQL 8.0的新特性之后,说说基于MySQL 8.0的高可用架构设计我们团队的架构是基于InnoDB Cluster+ 读写分离+ 分库分表的方案下面详细介绍。
1. InnoDB Cluster高可用集群:
我们的核心数据库用InnoDB Cluster搭建高可用集群一个集群有3个节点(1主2从)用Group Replication做数据同步支持自动故障转移,如果主库挂了会自动选举一个从库作为新主继续提供服务故障转移时间大概几秒到十几秒业务基本无感知。
用MySQL Router做路由应用连接MySQL Router而不是直接连接数据库MySQL Router会自动识别集群中的主库和从库把写请求路由到主库读请求路由到从库实现读写分离,而且,如果主库挂了MySQL Router会自动把写请求路由到新主不用应用改配置非常方便。
InnoDB Cluster的优点是原生支持高可用不用第三方工具配置简单维护方便数据一致性好故障转移自动可靠缺点是需要至少3个节点资源占用稍大,而且Group Replication对网络要求较高节点之间,网络要稳定低延迟适合同机房部署跨机房的话,需要注意网络延迟和带宽。
2. 读写分离:
我们用MySQL Router实现读写分离写请求(INSERTUPDATEDELETE)路由到主库读请求(SELECT)路由到从库这样能把读压力分散到多个从库提升整体的读并发能力特别是读多写少的应用效果很明显。
读写分离需要注意的问题是主从延迟,因为主从复制是异步的(Group Replication是同步的,但是也有微小的延迟)写到主库的数据可能需要一点时间才能同步到从库,如果写之后,立即读可能读不到最新的数据这就是主从延迟问题。
我们的解决方案是:
- 强制走主库:对于写之后,立即读的场景(比如提交订单后立即查看订单详情)强制这个读请求走主库保证能读到最新数据。
- 延迟检测:监控主从延迟,如果延迟超过阈值(比如1秒)就把读请求也路由到主库等延迟恢复了再切回从库保证数据一致性。
- 业务容忍:对于对数据一致性要求不高的场景(比如商品列表用户评论等等)允许短暂的延迟走从库提升并发能力。
3. 分库分表:
当数据量和并发量继续增长单库单表会成为瓶颈这时候就需要分库分表我们用ShardingSphere(以前叫Sharding-JDBC)做分库分表中间件把大表按某个字段(比如用户ID时间等等)拆分到多个库多个表分散数据量和压力提升并发能力。
我们的分库分表策略是:
- 垂直分库:按业务模块分库,比如用户库订单库商品库等等不同业务的数据放不同的库减少单库的压力也便于业务解耦和独立扩展。
- 水平分表:对于数据量大的表(比如订单表用户操作日志表等等)按用户ID或者时间水平拆分到多个表,比如订单表按用户ID取模拆成16张表分散数据量和查询压力。
- 读写分离+分库分表结合:每个分库都是一个InnoDB Cluster高可用集群支持读写分离这样整体架构既高可用又高并发能支撑很大的数据量和并发量。
分库分表需要注意的问题是分布式事务跨库查询排序分页等等这些都比较复杂ShardingSphere能帮我们处理大部分问题,但是还是需要在设计的时候,注意尽量避免跨库查询和分布式事务按分片键查询性能最好。
三、高并发优化
除了架构设计高并发优化也很重要我们从几个方面做了优化。
1. 连接池优化:
数据库连接的建立和销毁是很耗资源的特别是高并发场景下,如果每次请求都新建连接性能会很差,所以需要用连接池复用连接我们用HikariCP作为连接池它是目前性能最好的Java连接池(我们后端用Java)配置合理的连接池参数能大幅提升性能。
连接池的重要参数包括:
- maximumPoolSize:最大连接数这个不是越大越好太大会给数据库造成太大压力太小会导致请求等待连接一般根据数据库的处理能力和应用的并发量来设置我们一般设置为数据库CPU核心数的2倍左右,或者根据实际压测结果调整。
- minimumIdle:最小空闲连接数保持一定数量的空闲连接避免请求来了才新建连接提升响应速度。
- connectionTimeout:连接超时时间获取连接的最大等待时间超时就报错避免请求无限等待。
- idleTimeout:空闲连接超时时间空闲连接超过这个时间就被回收避免占用过多资源。
- maxLifetime:连接最大存活时间连接超过这个时间就被回收新建避免连接时间太长出现问题(比如数据库端断开连接等等)。
合理配置连接池参数能让连接复用效率最高数据库压力最小性能最好需要根据实际情况压测调整不是一成不变的。
2. SQL优化:
SQL优化是高并发优化的核心很多性能问题都是,因为SQL写得不好导致的我们从几个方面做SQL优化:
- 索引优化:合理创建索引是SQL优化最有效的手段给查询条件排序分组的字段创建合适的索引能大幅提升查询速度,但是索引不是越多越好太多索引会影响写性能也占用存储空间要合理创建MySQL 8.0支持降序索引隐藏索引等等能更好地优化索引。
- 避免全表扫描:尽量让查询走索引避免全表扫描特别是大表全表扫描性能很差用EXPLAIN分析查询计划看有没有走索引有没有全表扫描及时优化。
- 避免SELECT :只查询需要的字段不要用SELECT 查询不需要的字段会浪费IO和,内存也不利于覆盖索引的使用。
- 分页优化:大表的深度分页(比如LIMIT 100000, 10)性能很差,因为需要扫描前面的100000条数据优化方法是用游标分页(基于上一页的最后一条数据的ID来查询下一页)或者延迟关联(先查主键再关联查详情)提升分页性能。
- 避免复杂子查询:尽量用JOIN代替复杂的子查询,或者用CTE(MySQL 8.0支持)让查询更清晰优化器也更容易优化。
- 批量操作:批量插入更新删除比单条操作性能好很多减少SQL交互次数提升性能,但是批量大小要合适太大会导致锁时间长影响并发。
3. 缓存优化:
缓存是高并发优化的重要手段能大幅减少数据库的压力我们用Redis做缓存把热点数据缓存起来查询的时候,先查缓存缓存有就直接返回没有再查数据库,然后写入缓存这样大部分读请求都被缓存挡住了数据库压力大大降低。
我们的缓存策略包括:
- 热点数据缓存:把热点的商品信息用户信息配置数据等等缓存起来这些数据读多写少适合缓存。
- 缓存失效策略:用过期时间+ 主动更新的策略数据更新的时候,主动更新缓存,或者删除缓存,同时设置合理的过期时间避免数据不一致时间太长。
- 缓存穿透防护:用布隆过滤器,或者缓存空值防止缓存穿透(查询不存在的数据缓存没有每次都查数据库)。
- 缓存击穿防护:热点key过期的时候,用互斥锁,或者永,不过期+ 异步更新防止缓存击穿(大量请求,同时查数据库)。
- 缓存雪崩防护:缓存过期时间加随机值避免大量key同时过期导致缓存雪崩。
缓存能大幅提升读性能,但是也带来了数据一致性的问题需要根据业务场景选择合适的缓存策略平衡性能和一致性。
4. 数据库参数优化:
MySQL的参数配置对性能影响也很大我们根据服务器配置和,业务特点优化了一些重要参数:
- innodbbufferpool_size:InnoDB缓冲池大小这是最重要的参数缓冲池越大能缓存的数据和,索引就越多磁盘IO就越少性能越好一般设置为服务器内存的50%-70%(如果服务器只跑MySQL)。
- innodblogfile_size:InnoDB日志文件大小影响写性能和崩溃恢复时间太小会导致频繁刷盘影响写性能太大崩溃恢复时间长MySQL 8.0支持更大的日志文件一般设置为1GB-4GB。
- innodbflushlogattrx_commit:事务提交时日志刷盘策略设置为1是最安全的(每次提交都刷盘)但是,性能稍差设置为2性能更好(每秒刷盘)但是崩溃可能丢1秒数据根据业务对数据安全的要求选择。
- max_connections:最大连接数根据应用的并发量和,连接池配置设置太大会占用过多资源太小会导致连接不够用。
- innodbflushmethod:InnoDB刷盘方法Linux下一般设置为O_DIRECT避免操作系统缓存和,InnoDB缓冲池双重缓存浪费内存提升IO性能。
- charactersetserver:字符集建议设置为utf8mb4支持完整的Unicode包括emoji等等避免乱码问题。
参数优化需要根据实际情况压测调整没有万能的配置要结合服务器配置业务特点来优化。
四、踩过的坑
在升级MySQL 8.0和架构设计的过程中我们也踩了一些坑这里分享一下大家注意避开。
坑1:认证插件不兼容:
MySQL 8.0默认用cachingsha2password认证插件比5.7的mysqlnativepassword更安全,但是一些老的客户端和驱动不支持这个认证插件会导致连接失败我们升级后有一些老的应用连接不上数据库排查了很久才发现是认证插件的问题。
解决方案:升级客户端驱动到支持cachingsha2password的版本,或者把用户的认证插件改回mysqlnativepassword(ALTER USER 'user'@'%' IDENTIFIED WITH mysqlnativepassword BY 'password';)但是这样安全性会降低建议尽量升级驱动用新的认证插件。
坑2:Group Replication对网络要求高:
InnoDB Cluster用Group Replication做数据同步对网络要求比较高节点之间,网络要稳定低延迟我们一开始把一个节点放在另一个机房跨机房部署结果网络延迟高导致Group Replication性能很差经常出现延迟和超时甚至节点被踢出集群。
解决方案:Group Replication节点尽量部署在同一个机房,或者网络延迟很低的环境跨机房的话,要用专线保证网络质量,或者用传统的主从复制(异步或半同步)更适合跨机房场景。
坑3:分库分表后跨库查询复杂:
分库分表后一些以前简单的查询变成了跨库查询很复杂性能也差,比如按用户ID分库后按订单号查询就需要扫描所有分库性能很差,还有跨库的排序分页统计等等都很复杂。
解决方案:分库分表设计的时候,要考虑查询模式选择合适的分片键让大部分查询都能按分片键查询避免跨库查询对于必须跨库的查询可以用冗余数据,或者搜索引擎(比如Elasticsearch)来辅助查询不要直接跨库查性能太差。
坑4:缓存和数据库数据不一致:
用缓存后缓存和数据库的数据不一致是常见问题我们遇到过数据更新了,但是缓存没更新导致用户看到旧数据,或者缓存删除了,但是有并发请求把旧数据又写回缓存了等等。
解决方案:用合理的缓存更新策略,比如Cache Aside Pattern(更新数据库后删除缓存而不是更新缓存)设置合理的过期时间作为兜底对于并发场景用互斥锁防止缓存击穿和旧数据写回对于数据一致性要求高的场景考虑不用缓存,或者用更强的一致性方案。
五、写在最后
以上就是我们团队升级MySQL 8.0和高可用高并发架构设计的实践分享包括MySQL 8.0的重要新特性高可用架构设计(InnoDB Cluster读写分离分库分表)高并发优化(连接池SQL优化缓存参数优化)以及踩过的坑。
MySQL 8.0是一个非常优秀的版本性能高可用安全等方面都有很大的提升特别是InnoDB Cluster让MySQL的高可用方案更简单更可靠推荐大家升级到8.0享受新特性带来的便利。
高可用高并发架构设计是一个系统工程需要从多个方面综合考虑数据库架构SQL优化缓存参数调优等等都很重要没有,银弹需要根据业务特点和实际情况选择合适的方案不断优化和调整。
希望我们的实践经验能帮大家更好地使用MySQL 8.0设计高可用高并发的数据库架构少走弯路。
最后用一句话结束这篇文章:"MySQL 8.0很强大高可用高并发架构设计需要综合考虑不断优化才能支撑业务的增长给用户稳定流畅的体验。"
愿大家的数据库都能稳定高效运行支撑业务蓬勃发展。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录