数据库的分库分表、读写分离和主从复制
与精品技术文章不期而遇
1.分库分表
分表
分为垂直划分和水平划分
垂直划分:
把不同功能,不同使用频率的数据列分别放到不同的表中
例如:把常用的字段放一个表,不常用的放一个表。使用的话是根据具体业务来拆,查询时使用多表联查,可以再配合redis存储。
水平划分
垂直切分解决不了大表的瓶颈,如果同一个功能中表的数据量过大,就要对该表进行切分,为水平切分。
例如:通过id取模划分,对10取模的话就可以分10张表。
分库
垂直分库:
按照业务模块来划分出不同的数据库
例如:商场订单模块放主机1中数据库, 商品模块放主机2中数据库。
水平分库:
主要根据数据属性(如商品所属地市, 种类)拆分物理数据库。
分库分表存在的问题
1.水平分表出现的id自增问题
解决方案:
1.java中的uuid
2.不同数据库步长不同自增
3.通过redis的单线程取到自增的id后加到不同数据库中
4.雪花算法,是通过不同机器的系统时间和机器编号计算的
5.美团的leaf
2.垂直分表出现的多表join,order问题
1.字段冗余(各个表中有相同的常用字段)
2.系统层组装(缓存中台)
3.分布式事务
详情见:https://www.jianshu.com/p/2f258139306d
2.主从复制
什么是主从复制?有什么好处?
是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是准实时的业务数据库。从数据库做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。保证了数据库的高可用。
主从复制的原理?
1.主数据库有个bin-log二进制文件,记录了所有sql语句。
2.我们的目标就是把主数据库的bin-log文件的sql语句复制过来。
3.让其在从数据的relay-log重做日志文件中再执行一次这些sql语句即可。
怎么保证主从的一致性?
简单介绍下两种方法:
方法1:在从表中写成功后才返回成功。
方法2: cache中设一个key记录着一次写的数据,然后设置一个同步时间,如果在这个时间内,有一个读请求,看看对应的key有没有相关数据,有的话,说明数据近期发生过写事件,这样key的数据就继续读主库,否则就读从库。
3.读写分离
什么是读写分离?
读写分离 一般有至少两个数据库 一个主数据库,一个从数据库,主数据库用来写操作,从数据库用来读操作。
什么情况下适合读写分离?
读写分离适用于读远大于写的场景,如果只有一台服务器,当select很多时,update和delete会被这些select访问中的数据堵塞,等待select结束,并发性能不高。对于写和读比例相近的应用,应该部署双主相互复制
读写分离有什么好处?
1.主从只负责各自的写和读,极大程度的缓解X锁和S锁争用(如果读操作被设置为锁的话,Innodb一般不会对select加锁,不管是不是在事务中。)
2.分摊读取。假如我们有1主3从,不考虑上述1中提到的从库单方面设置,假设现在1 分钟内有10条写入,150条读取。那么,1主3从相当于共计40条写入,而读取总数没变,因此平均下来每台服务器承担了10条写入和50条读取(主库不 承担读取操作)。因此,虽然写入没变,但是读取大大分摊了,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了,说白 了就是拿机器和带宽换性能。
读写分离之后还能优化吗?
1.从库可配置myisam引擎,提升查询性能以及节约系统开销。
2.可以在从库启动时增加一些参数来提高其读的性能,例如--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL。当然这些设置也是需要根据具体业务需求来定的,不一定能用上。
麻烦点一下在看再走呗