1、池化技术
用连接池预先建立数据库连接(1 独立线程检查可用性 2 用前先确定可用性)
如果当前连接数小于最小连接数,则创建新的连接处理数据库请求;
如果连接池中有空闲连接则复用空闲连接;
如果空闲池中没有连接并且当前连接数小于最大连接数,则创建新的连接处理请求;
如果当前连接数已经大于等于最大连接数,则按照配置中设定的时间(C3P0 的连接池配置是 checkoutTimeout)等待旧的连接可用;
如果等待超过了这个设定时间则向用户抛出错误。
用线程池预先创建线程

2、数据库主从分离
主从复制

延时问题
第一种方案是数据的冗余。你可以在发送消息队列时不仅仅发送微博 ID,而是发送队列处理机需要的所有微博信息,借此避免从数据库中重新查询数据。
第二种方案是使用缓存。我可以在同步写数据库的同时,也把微博的数据写入到 Memcached 缓存里面,这样队列处理机在获取微博信息的时候会优先查询缓存,这样也可以保证数据的一致性。
最后一种方案是查询主库。我可以在队列处理机中不查询从库而改为查询主库。不过,这种方式使用起来要慎重,要明确查询的量级不会很大,是在主库的可承受范围之内,否则会对主库造成比较大的压力。
如何访问数据库
第一类以淘宝的 TDDL( Taobao Distributed Data Layer)为代表,以代码形式内嵌运行在应用程序内部。
另一类是单独部署的代理层方案,这一类方案代表比较多,如早期阿里巴巴开源的 Cobar,基于 Cobar 开发出来的 Mycat,360 开源的 Atlas,美团开源的基于 Atlas 开发的 DBProxy 等等。
3、分库分表
分库分表有两种方式:垂直拆分和水平拆分
垂直拆分的关注点在业务相关性,原则是按照业务拆分,核心思想是专库专用,将业务耦合度高的拆分到单独库中
水平拆分是把单一数据库按照某种规则拆分到多个数据库和多个数据表中,关注点在数据的特点
水平拆分的两种方法
1.根据某个字段的hash值拆分
比如想把用户表拆成16库64表,方案如下
先对id进行hash操作hash(id),这样有助于打散数据
然后对16取余 hash(id)%16,这样就得到了分库后的索引
最后对64取余 hash(id)%16%64,这样就得到了分表后的索引值
2.根据某个字段的区间或范围拆分
可以根据时间拆分
3.hash和range结合


引入分库分表确实有很多优点,但也会引入新的问题
1.引入了分区分表键,也叫分区键
因为我们需要对分区键进行hash进行索引,这样就导致我们查询都要带上该分区键,比较好的解决办法是用id做分区键,但是如果有根据用户昵称查询的需求怎么办呢?
解决办法就是建立一个昵称和id的映射表
2.一些数据库的特性的实现变得困难
(1)夸库join不可用
解决办法是在业务代码中做处理
(2)求count
采取第三方组件例如redis实现
4、ID全局唯一性
1、 使用业务字段作为主键
2、发号器的实现思路
2-1:机器号+时间戳来实现
2-2:基于uuid实现
2-3:基于数据自增主键实现
2-4:基于redis加一指令实现
2-5:基于zk实现
2-6:基于开源的雪花算法实现,或者参考其他公司开源的发号器实现,比如:百度、腾讯、美团