mysql和redis数据同步方案
mysql集群主从复制 解决单点故障问题
2、高可用方案 对外提供是一个主节点,投票
3、横向扩展cluster集群 对外提供多个主节点
怎么优化单个主节点的处理能力?
主节点master 发生了写操作,数据进行了变更,binlog里面将会有记录
这时候从节点slave 开启io线程 读取master节点的binlog日志,然后生成一个中继日志 relay log,再由 sql线程读取这个relay log日志,回放,写入到从节点中,这样就完成了同步。
当客户端写入数据到master节点之后,就立马返回结果给客户端,当然了,此时也在binlog日志的内容写入到 slave节点的relay log中继日志里面
当客户端写入数据到master节点之后,先不急就将结果返回到客户端,而是先等待,先把binlog日志里面的变化内容写入到slave节点中,然后再返回结果信息给客户端
这样就解决了一个客户端A写数据到 master节点,同时又有一个客户端B来读,此时读的就是slave节点,如果是异步的方式,那么此时可能数据还没有同步到slave节点,这样读的数据可能就会不一致了。
但是引入了一个问题:写延迟
单主节点,异步复制,在这种情况下怎么优化处理能力?
弄一个数据库中间件作为路由
先写redis,再异步去写mysql,最后让mysql复写给redis
先写redis,redis要加一个过期时间:
为什么要加过期时间:
1、如果redis挂了,那么等redis好了之后,再重写就可以了
2、如果mysql挂了,那么redis存进去之后也就马上就消失了,这样这条写入操作也相当于废掉了
最初级的数据库和缓存数据不一致问题:就是删除缓存这个操作失败了,也就是这个操作没有生效。
解决思路一:
先删除缓存,再更新数据库,如果数据库更新失败了,则缓存中因为没有数据,就会去读数据库,因为数据库更新失败了,就还是旧值,这样就不会导致数据库和缓存中的数据不一致。
当队列中读请求 从队列中出来的时候,会去Mysql中读取数据,然后将读取到的数据,更新到redis中,这个操作其实是有点耗时的,因此,如果有多个读请求,不需要将所有的读请求都放到队列中,因为读请求都会执行 先读 然后 更新到redis的操作的!!!
所以如果队列里面有读请求了,这时又来了很多相同商品id的读请求,这时是没必要进队列的,只需要在外面一直循环,不断的读取Redis中的数据就可以了,如果在200ms 还没有读到数据,就直接去mysql中取数据,取到之后就返回回去
如果一个队列中居然会积压100个商品的库存的修改操作,每个库存修改操作都要花费10ms完成,那么最后一个商品的读请求就会等待1s的时间,才能得到数据,这样读请求长期阻塞。
所以一定要做压力测试。
如果最繁忙的时候,也都积压了10个更新请求,那还可以!
但如果积压了100多个更新请求,那么就要加机器了,
可以按照请求的某个参数做hash路由
热点商品的请求全部打到某个队列中,可能造成某台机器压力过大
如果更新频率不大,这个问题的影响不大,但这个机器的负载确实会高一些