当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:
- 限定数据的范围:务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。
- 分库分表:主要有垂直分表和水平分表。
- 主从复制+读写分离:经典的数据库拆分方案,主库负责写,从库负责读。
- 缓存:使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存,比如memcache和redis等。
分库分表
分库分表包括分库和分表两个部分,在生产中通常包括:垂直分表、垂直分库、水平分表、水平分库四种方式。
垂直分表
把主键和一些列放在一个表,然后把主键和另外的列放在另一个表中。
垂直分表的优点
- 避免IO争抢并减少锁表的几率,查看详情的用户与商品信息浏览互不影响。
- 充分发挥热门数据的操作效率,商品信息的操作的高效率不会被商品描述的低效率所拖累。
垂直分表的缺点
- 有些分表的策略基于应用层的逻辑算法,一旦逻辑算法改变,整个分表逻辑都会改变,扩展性较差。
- 对于应用层来说,逻辑算法增加开发成本。
- 管理冗余列,查询所有数据需要join操作。
垂直分库
垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。
垂直分库的优点
- 解决业务层面的耦合,业务清晰。
- 能对不同业务的数据进行分级管理、维护、监控、扩展等。
- 高并发场景下,垂直分库一定程度的提升IO、数据库连接数、降低单机硬件资源的瓶颈。
垂直分库的缺点
- 依然没有解决单表数据量过大的问题。
水平分表
保持数据表结构不变,通过某种策略将存储数据分片,这样每一片数据分散到不同的表中。 水平拆分可以支撑非常大的数据量。
水平分表的优点
- 优化单一表数据量过大而产生的性能问题。
- 避免IO争抢并减少锁表的几率。
水平分表的缺点
- 给应用增加复杂度,通常查询时需要多个表名,查询所有数据都需UNION操作。
- 在许多数据库应用中,这种复杂度会超过它带来的优点,查询时会增加读一个索引层的磁盘次数。
水平分库
水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。
水平分库的优点
- 解决了单库大数据,高并发的性能瓶颈。
- 提高了系统的稳定性及可用性。
水平分库的缺点
- 同一个表被分配在不同的数据库,需要额外进行数据操作的路由工作,因此大大提升了系统复杂度。
主从复制+读写分离
主从复制
将主数据库中的DDL和DML操作通过二进制日志(BINLOG)传输到从数据库上,然后将这些日志重新执行(重做);从而使得从数据库的数据与主数据库保持一致。
主从复制的过程
- 主服务器上面启动一个binlog线程,主服务器的任何修改都会保存在Binary log(二进制日志)里面。
- 从服务器上面启动一个I/O线程,连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log(中继日志)里面。
- 从服务器上面开启一个SQL线程,定时检查Realy log,如果发现有更改立即把更改的内容在本机上面执行一遍。
主从复制的模式
- 异步复制模式:主库接受到客户请求后,处理完事务后,立即将结果返给客户端,不去关系从库是否已经接收并处理。客户体验度高,访问从库可能没有数据
- 全同步复制:当主库执行完一次事务,且所有从库都接受并处理之后,才返回给客户端。客户体验度差,数据同步好。
- 半同步复制:介于两种模式之间,主库执行一次事务后,等待至少一个从库接受并写到relay log中才返回给客户端。目前大多数企业采用的方法
主从复制的优点
- 做数据的备份,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
- 降低磁盘I/O访问的评率,提高单个机器的I/O性能。
- 读写分离,使数据库能支持更大的并发。如果进程A使用master,进程B使用slave,那么进程B将不会影响进程A的速度。
读写分离
读写分离是依赖于主从复制,而主从复制又是为读写分离服务的。因为主从复制要求slave不能写只能读。
通过设置主从数据库实现读写分离,主数据库负责“写操作”,从数据库负责“读操作”,根据压力情况,从数据库可以部署多个提高“读”的速度,借此来提高系统总体的性能。
缓存
redis
Redis是一个使用 C 语言开发的数据库,不过与传统数据库不同的是Redis 的数据是存在内存中的,也就是它是内存数据库,所以读写速度非常快,因此Redis被广泛应用于分布式缓存方向。
关于redis的详解请移步redis专栏。
memcache
memcache是一个高性能的分布式的内存对象缓存系统。memcache主要用于分担数据库的压力,它通过在内存里维护一个统一的巨大hash表来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等,以此来减少读取数据库的次数,从而提高动态、数据库驱动网站速度。
memcache的流程
- 检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作,路径操作为①②③⑦。
- 如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现),路径操作为①②④⑤⑦⑥。
- 每次更新数据库的同时更新memcached中的数据,保证一致性。
- 当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
|