【持续更新中】架构面试知识学习总结
1.分库分表出现冗余数据:
☆分库分表方法:水平和垂直(业务场景,数据关联性。逻辑要调查清楚)
垂直:将一个表(库)按照列的业务相关性进行拆分,把经常一起使用的列放在一张表(库),不经常一起使用的列放在另一张表。
目的:减少数据冗余:去除不常用或很少使用的列,使每张表的数据更紧凑。
提高查询性能:针对特定业务场景的查询,可以只操作相关的表,减少数据量,提高查询效率。
便于维护:表结构更清晰,更易于理解和维护。
水平:按照某种规则(比如去摸)将数据行均匀分布到多个表中。
目的:解决单表数据量过大的问题,提高数据的写入和查询性能。
支持分布式存储和扩展,便于水平扩展数据库的容量。
都是为了将热点数据放在一起,方便查询,避免用join。 工具sharding-jdbc 和macat(mysql的代理,需要单独维护这个服务)
☆步骤:
1.调查读和写的并发量,以及数据量 确定分库和表的数量
2.选Key,选定分库分表的规则。
3.执行 一般双写
3.扩容场景,需要DBA的准备,负责数据的迁移
☆分表问题:
单key业务
1.需要索引表。做索引映射,必须找到key。性能差,可以结合redis,使用缓存映射
有缓存穿透,雪崩等问题要考虑
2.基因算法
用检索条件字段的数据生成64位数 用数的后四位作为基因转成10进制,然后根据数据表(库)个数取模,结果为几号表或库
这样插入目标表(库)后。检索时,同样规则用该检索条件数据生成64位数,也就也能找到对应目标表(库)。结合雪花算法使用
雪花算法(Snowflake)是一种生成分布式唯一 ID 的算法。
它生成的 ID 通常是一个 64 位的整数,由以下几个部分组成:
1 位符号位:固定为 0,以保证生成的 ID 为正数。
41 位时间戳:表示毫秒级的时间,能使用大约 69 年。
10 位工作机器 ID:可以标识不同的机器节点。
12 位序列号:在同一毫秒内,用于生成不同的 ID 。
雪花算法的优点包括:
生成的 ID 是趋势递增的,便于数据库索引和排序。
分布式环境下能保证不同机器生成的 ID 不重复。
生成效率高,能满足高并发场景的需求。
在实际应用中,雪花算法常用于分布式系统中生成唯一标识符,如数据库主键、分布式任务的标识等
多Key业务(一般是分库或者是垂直分表时用的):也可以用但Key业务的索引映射方法外,还可以做冗余法(类似基因算法)。需要数据同步
・应用层代码解决
・sharedingSphere
・MQ
2.分布式事务 唯一键生成
・按照取模的方式。分成不同区间的起始号码
・指定号段,一个号段区间先用。用完了进入新的库表的号段
・使用UUID 这个插入会相对性能下降。影响mysql平衡二叉树的平衡。解决:使用主键ID和唯一主键用UUID。主键ID用于二叉树平衡。用UUID用于业务处理
・Redis:Jedis.incr(key) 需要将这些在redis数据持久化方式。否则有丢失风险 性能最好。但是有并发安全问题。即数据库和redis不一致
・雪花算法:3部分组成 第一部分41bit为的时间戳(精确到毫秒) 第二部分10bit位 程序员指定的数 第三部分为12bit位的序列号组成 用这个来生成唯一ID 但是时间回拨会出现问题
java中hutool来实现
3.分布式锁:mysql Zookeeper redis
・基于数据库的分布式锁,定义一个管理事务的表,保存锁资源信息和状态。根据是否被占用来使用该数据
需要互斥,平衡等机制要自己实现。
・redis(推荐):setNx存一个值,其他线程发现这个里边值已经存在,说明锁被占用。就自旋确认锁状态。通常使用redisson实现,里边有watchDog这个机制,给对于长时间处理的线程的锁续命用的。
使用红锁,将主从节点都加上锁。不管使用哪个节点都能保证上锁 不会被乱用,不是100%保证 。高效率分布式锁
需要lua脚本
・ZK:是CP模式,根据线程顺序,来创建锁以及锁的顺序。ZK监听器会监听各个锁状态。随着线程处理结束,顺序下去获得锁。属于重的分布式锁
常用redis,MQ
3.多级缓存:
是利用请求处理的每个环节,分别添加缓存,减轻tomcat压力,提升服务器性能
客户端,应用层,服务端部分的缓存
客户端缓存:
1.客户浏览器,CSS,IMG等静态资源的缓存.通过Expires来设定过期时间,实现缓存有效期
可以使用nginx和CDN方式来:
☆CDN:重量级解决方案
客户端->网络提供商的智能DNS->就近转发到CDN节点. 如果资源存在 直接返回不会去访问主数据源节点
阿里云等提供CDN节点服务
Expires:通知客户端设置到什么时间点缓存超时,cache-conctrol:是通知客户端浏览器 设置多长时间缓存超时
☆nginx:请两级软缓存
静态资源直接在nginx服务器中缓存
服务层缓存:进程内和外缓存 两部分
☆进程外缓存:就是分布式缓存,典型的时redis.对整体架构中的数据,整体数据缓存.
☆进程内缓存:在一个应用中,开辟本地内存空间,数据在运行时放入其中,在本地开启一块空间.本地内存高吞吐低延迟
比如:springmvc页面缓存,hibernate,mybaties1,2级缓存.
在java侧Caffeine,ehcache 等
☆课题:缓存和数据库的数据一致性问题(MQ,DB见分布式锁.Redisson中间件)
缓存方案:由近到远,由快到慢的方针.(不是一定是redis.通常java侧有ehcache缓存,当echcache没数据才去redis中找)
利用多级缓存的适合场景:
1.缓存的数据是稳定的;
2.顺势可能产生极高并发的场景;(热点数据分发到各个节点缓存)
3.一定程度上允许数据不一致(比如个人博客 自我介绍,不需要高效的同步)