27.spring都有哪些机制啊AOP底层如何实现的啊IOC呢??
简而言之IOC依赖注入,就是单例模式。底层就是一个spring的注册中心一样的东西,无论是xml配置还是注解的方式都会将其读取生成beandefinition,获取时有两种方式,一种是在注册时就创建单例,还有一种是第一次调用时。(当然也可以选择多例模式)
AOP是面向切面编程,可以自定义一些规则在执行方法前后进行相应的处理。所使用的方法是动态代理。
28.cgLib知道吗?他和jdk动态代理什么区别?手写一个jdk动态代理呗?
jdk的动态代理需要基于接口,他是在程序运行时通过继承原有类的接口封装原有类的方法和切入逻辑生成一个代理类进行处理。必须要有接口。
而cglib则不需要,它使用动态字节码生成技术实现AOP原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中。
public class LogInvocationHandler implements InvocationHandler {
private Object target;//目标对象
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行织入的日志,你可以控制哪些方法执行切入逻辑
if (method.getName().equals("doSomeThing2")) {
System.out.println("记录日志");
}
//执行原有逻辑
Object recv = method.invoke(target, args);
return recv;
}
}
数据库
29.使用mysql索引都有哪些原则? ?索引什么数据结构? B+tree 和B tree 什么区别?
索引使用原则
** 为值唯一的建立唯一索引,可以直接通过值查询到对应记录。
** 为经常需要使用该字段进行排序、分组和联合操作的字段建立索引
** 为常作为查询条件的字段建立索引
** 限制索引的数目:
索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。
尽量使用数据量少的索引:
如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR(100)类型的字段进行全文检索需要的时间肯定要比对CHAR(10)类型的字段需要的时间要多。
** 尽量使用前缀来索引:
如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。
** 尽量选择区分度高的列作为索引:
区分度的公式是count(distinct col)/count(**),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,一般要求索引的字段区分度最少保证在0.1以上。
索引列不能参与计算,保持列“干净”:
比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本 太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
** 尽量的扩展索引,不要新建索引:
比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可
索引的数据结构
常见的有b tree b+tree 散列 通讯R-树
B+tree和B Tree的区别
** B Tree索引结构:
一个根节点 可以有数据可以没有 且根节点只能储存一个数据
设定一个宽度 作为每个节点存储的数据 设为d
每个子节点有d/2到d-1个数据 有对应数据数+1的指针(孩子节点)
每个个节点储存的数据都是从左到右按大小排列的
查找时比较大小进入对应的子节点使用二分法继续查找 递归向下直到查找到对应的数据,或者查询出null(失败)
由于插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质。
** b+tree
b tree的变种
变化如下:
每个节点的指针上限为2d而不是2d+1
内节点不存储data,只存储key
叶子节点不存储指针
由于并不是所有节点都具有相同的域,因此B+Tree中叶节点和内节点一般大小不同。这点与B-Tree不同,虽然B-Tree中不同节点存放的key和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中B-Tree往往对每个节点申请同等大小的空间。一般来说,B+Tree比B-Tree更适合实现外存储索引结构
带有顺序访问指针的B+Tree:一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针。
在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能。
区别:
B+树中只有叶子节点会带有指向记录的指针(ROWID),而B树则所有节点都带有,在内部节点出现的索引项不会再出现在叶子节点中。
B+树中所有叶子节点都是通过指针连接在一起,而B树不会。
B+树的优点:
1.非叶子节点不会带上指针,这样,一个块中可以容纳更多的索引项,一是可以降低树的高度。二是一个内部节点可以定位更多的叶子节点。
2.叶子节点之间通过指针来连接,范围扫描将十分简单,而对于B树来说,则需要在叶子节点和内部节点不停的往返移动。
B树的优点:
对于在内部节点的数据,可直接得到,不必根据叶子节点来定位。
30.MySQL有哪些存储引擎啊?都有啥区别? 要详细!
MyISAM
这种引擎是mysql最早提供的。这种引擎又可以分为静态MyISAM、动态MyISAM 和压缩MyISAM三种:
** 静态MyISAM:如果数据表中的各数据列的长度都是预先固定好的,服务器将自动选择这种表类型。因为数据表中每一条记录所占用的空间都是一样的,所以这种表存取和更新的效率非常高。当数据受损时,恢复工作也比较容易做。
** 动态MyISAM:如果数据表中出现varchar、xxxtext或xxxBLOB字段时,服务器将自动选择这种表类型。相对于静态MyISAM,这种表存储空间比较小,但由于每条记录的长度不一,所以多次修改数据后,数据表中的数据就可能离散的存储在内存中,进而导致执行效率下降。同时,内存中也可能会出现很多碎片。因此,这种类型的表要经常用optimize table 命令或优化工具来进行碎片整理。
** 压缩MyISAM:以上说到的两种类型的表都可以用myisamchk工具压缩。这种类型的表进一步减小了占用的存储,但是这种表压缩之后不能再被修改。另外,因为是压缩数据,所以这种表在读取的时候要先时行解压缩。
MyISAM Merge引擎:这种类型是MyISAM类型的一种变种。合并表是将几个相同的MyISAM表合并为一个虚表。常应用于日志和数据仓库。
InnoDB:InnoDB表类型可以看作是对MyISAM的进一步更新产品,它提供了事务、行级锁机制和外键约束的功能。
memory(heap):这种类型的数据表只存在于内存中。它使用散列索引,所以数据的存取速度非常快。因为是存在于内存中,所以这种类型常应用于临时表中。
archive:这种类型只支持select 和 insert语句,而且不支持索引。常应用于日志记录和聚合分析方面。
31.设计高并发系统数据库层面该怎么设计??数据库锁有哪些类型?如何实现呀?
高并发设计
数据库层面随着并发量和访问量的增加,会经历一系列转型
1. WEB应用和数据库部署在同一台服务器上:用户量、数据量、并发访问量都比较小
2. WEB应用和数据库部署在各自独立的服务器上:在系统访问量增加的时候可以分别升级应用服务器和数据库服务器,这种部署方式是一般小规模网站的典型部署方式。
3. 数据库服务器采用集群方式部署:数据库集群方式能承担的负载是比较大的,数据库物理介质为一个磁盘阵列,多个数据库实例以虚拟IP方式向外部应用服务器提供数据库连接服务。这种部署方式基本上可以满足绝大多数的常见WEB应用,但是还是不能满足大用户量、高负载、数据库读写访问非常频繁的应用。
mysql集群的规划
mysql集群由管理节点、数据节点、mysql节点组成。一般情况下数据节点和mysql可以放在统一服务器,管理节点在另外一个服务器。本例中采用三台服务器,一台作为管理节点,另外两台同时作为数据和mysql节点,可以用下图表示:
4. 数据库采用主从部署方式:在面向大众用户的博客、论谈、交友、CMS等系统中,有上百万的用户,有上千万的数据量,存在众多的数据库查询操作,也有较多的数据库写操作,并且在多数情况下都是读操作远大于写操作的。于是就有了主从部署。
** 主从复制:
几乎所有的主流数据库都支持复制,这是进行数据库简单扩展的基本手段。下面以Mysql为例来说明,它支持主从复制,配置也并不复杂,只需要开启主服务器上的二进制日志以及在主服务器和从服务器上分别进行简单的配置和授权。Mysql的主从复制是依据主服务器的二进制日志文件进行的,主服务器日志中记录的操作会在从服务器上重放,从而实现复制,所以主服务器必须开启二进制日志,自动记录所有对于主数据库的更新操作,从服务器再定时到主服务器取得二进制日志文件进行重放则完成了数据的复制。主从复制也用于自动备份。
** 读写分离:
为保证数据库数据的一致性,我们要求所有对于数据库的更新操作都是针对主数据库的,但是读操作是可以针对从数据库来进行。大多数站点的数据库读操作比写操作更加密集,而且查询条件相对复杂,数据库的大部分性能消耗在查询操作上了。
主从复制数据是异步完成的,这就导致主从数据库中的数据有一定的延迟,在读写分离的设计中必须要考虑这一点。以博客为例,用户登录后发表了一篇文章,他需要马上看到自己的文章,但是对于其它用户来讲可以允许延迟一段时间(1分钟/5分钟/30分钟),不会造成什么问题。这时对于当前用户就需要读主数据库,对于其他访问量更大的外部用户就可以读从数据库。
** 数据库反向代理:
在读写分离的方式使用主从部署方式的数据库的时候,会遇到一个问题,一个主数据库对应多台从服务器,对于写操作是针对主数据库的,数据库个数是唯一的,但是对于从服务器的读操作就需要使用适当的算法来分配请求啦,尤其对于多个从服务器的配置不一样的时候甚至需要读操作按照权重来分配。
对于上述问题可以使用数据库反向代理来实现。就像WEB反向代理服务器一样,MYsql Proxy同样可以在SQL语句转发到后端的Mysql服务器之前对它进行修改。
5. 数据库垂直分割:主从部署数据库中,当写操作占了主数据库的CPU消耗的50%以上的时候,我们再增加从服务器的意义就不是很大了,因为所有的从服务器的写操作也将占到CPU消耗的50%以上,一台从服务器提供出来查询的资源非常有限。数据库就需要重新架构了,我们需要采用数据库垂直分区技术啦。
最简单的垂直分区方式是将原来的数据库中独立的业务进行分拆(被分拆出来的部分与其它部分不需要进行Join连接查询操作),比如WEB站点的BLOG和论坛,是相对独立的,与其它的数据的关联性不是很强,这时可以将原来的的数据库拆分为一个BLog库,一个论坛库,以及剩余的表所组成的库。这三个库再各自进行主从数据库方式部署,这样整个数据库的压力就分担啦。
另外查询扩展性也是采用数据库分区最主要的原因之一。将一个大的数据库分成多个小的数据库可以提高查询的性能,因为每个数据库分区拥有自己的一小部分数据。假设您想扫描1亿条记录,对一个单一分区的数据库来讲,该扫描操作需要数据库管理器独立扫描一亿条记录,如果您将数据库系统做成50个分区,并将这1亿条记录平均分配到这50个分区上,那么每个数据库分区的数据库管理器将只扫描200万记录。
6. 数据库水平分割:在数据库的垂直分区之后,假如我们的BLOG库又再次无法承担写操作的时候,我们又该怎么办呢?数据库垂直分区这种扩展方式又无能为力了,我们需要的是水平分区。
水平分区意味着我们可以将同一个数据库表中的记录通过特定的算法进行分离,分别保存在不同的数据库表中,从而可以部署在不同的数据库服务器上。很多的大规模的站点基本上都是主从复制+垂直分区+水平分区这样的架构。水平分区并不依赖什么特定的技术,完全是逻辑层面的规划,需要的是经验和业务的细分。
如何分区呢?对于大型的WEB站点来说,必须分区,并且对于分区我们没有选择的余地,对于那些频繁访问导致站点接近崩溃的热点数据,我们必须分区。
在对数据分区的时候,我们必须要存在一个分区索引字段,比如USER_ID,它必须和所有的记录都存在关系,是分区数据库中的核心表的主键,在其它表中作为外键,并且在使用主键的时候,该主键不能是自增长的,必须是业务主键才可以。
数据库锁
共享(S)锁:多个事务可封锁一个共享页;任何事务都不能修改该页; 通常是该页被读取完毕,S锁立即被释放。
排它(X)锁:仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。
更新(U)锁:用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。
32.数据库事务有哪些?
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
1. 事务是作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为 ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为一个事务:
原子性
2. 事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性
3. 事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。
隔离性
4. 由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它 之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态 相同。
持久性
5. 事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
开启事务start transaction
回滚事务rollback
提交事务commit
多线程事务问题
1. 脏读:A事务读取B事务尚未提交的更改数据
2. 不可重复读:不可重复读是指A事务读取了B事务已经提交的更改数据
不可重复读的重点是修改: 同样的条件, 你读取过的数据, 再次读取出来发现值不一样了
3. 幻读:A事务读取B事务提交的新增数据
幻读的重点在于新增或者删除 (数据条数变化)。同样的条件, 第1次和第2次读出来的记录数不一样
4. 第一类丢失更新:A事务撤销时,把已经提交的B事务的更新数据覆盖了。
5. 第二类丢失更新:A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失
事务隔离级别
1. Read UnCommitted(读未提交)
最低的隔离级别。一个事务可以读取另一个事务并未提交的更新结果。
2. Read Committed(读提交)
大部分数据库采用的默认隔离级别。一个事务的更新操作结果只有在该事务提交之后,另一个事务才可以的读取到同一笔数据更新后的结果。
3. Repeatable Read(重复读)
mysql的默认级别。整个事务过程中,对同一笔数据的读取结果是相同的,不管其他事务是否在对共享数据进行更新,也不管更新提交与否。
4. Serializable(序列化)
最高隔离级别。所有事务操作依次顺序执行。注意这会导致并发度下降,性能最差。通常会用其他并发级别加上相应的并发锁机制来取代它。
分库分表
33.如何设计可以动态扩容缩容的分库分表方案?
建立查询主键与数据库的映射关系 中间建立虚拟库关系。
1. 需要存储数据前,先根据ID(数据中总是带有ID),切换数据源
2. 数据源查找的过程,基本上是对上述两张元数据表进行查找,先找到虚拟库ID,进而找到实际的库连接信息。
3. 需要提取数据时,也按照上述方法找到实际的库连接信息,进行数据源切换。
34.用过哪些分库分表中间件,有啥优点和缺点?讲一下你了解的分库分表中间件的底层实现原理?
Cobar
提供关系型数据库(MySQL)分布式服务的中间件,它可以让传统的数据库得到良好的线性扩展,并看上去还是一个数据库,对应用保持透明。
Cobar以Proxy的形式位于前台应用和实际数据库之间,对前台的开放的接口是MySQL通信协议,将前台SQL语句变更并按照数据分布规则发到合适的后台数据分库,再合并返回结果,模拟单库下的数据库行为。
Cobar属于中间层方案,在应用程序和MySQL之间搭建一层Proxy。中间层介于应用程序与数据库间,需要做一次转发,而基于JDBC协议并无额外转发,直接由应用程序连接数据库,性能上有些许优势。这里并非说明中间层一定不如客户端直连,除了性能,需要考虑的因素还有很多,中间层更便于实现监控、数据迁移、连接管理等功能。
现在Cobar已经停止维护
MyCAT
社区爱好者在阿里cobar基础上进行二次开发,解决了cobar当时存 在的一些问题,并且加入了许多新的功能在其中。目前MyCAT社区活 跃度很高,目前已经有一些公司在使用MyCAT。总体来说支持度比较高,也会一直维护下去,发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL, SQL Server, Oracle, DB2, PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。
MyCAT是一个强大的数据库中间件,不仅仅可以用作读写分离,以及分表分库、容灾管理,而且可以用于多租户应用开发、云平台基础设施,让你的架构具备很强的适应性和灵活性,借助于即将发布的MyCAT只能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表隐射到不同存储引擎上,而整个应用的代码一行也不用改变。
MyCAT是在Cobar基础上发展的版本,两个显著提高:后端由BIO改为NIO,并发量有大幅提高; 增加了对Order By, Group By, Limit等聚合功能
TDDL
是Tabao根据自己的业务特点开发的
主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个基于集中式配置的jdbc datasourcce实现,具有主备,读写分离,动态数据库配置等功能。
TDDL源码:https://github.com/alibaba/tb_tddl
DRDS:是阿里巴巴自主研发的分布式数据库服务(此项目不开源)
Atlas
Atlas是一个位于应用程序与MySQL之间的基于MySQL协议的数据中间层项目,它是在mysql-proxy 0.8.2版本上对其进行优化,360团队基于mysql proxy 把lua用C改写,它实现了MySQL的客户端和服务端协议,作为服务端与应用程序通讯,同时作为客户端与MySQL通讯。它对应用程序屏蔽了DB的细节。
Altas不能实现分布式分表,所有的字表必须在同一台DB的同一个DataBase里且所有的字表必须实现建好,Altas没有自动建表的功能。
原有版本是不支持分库分表, 目前已经放出了分库分表版本。
DBProxy
美团点评DBA团队针对公司内部需求,在奇虎360公司开源的Atlas做了很多改进工作,形成了新的高可靠、高可用企业级数据库中间件
其特性主要有:读写分离、负载均衡、支持分表、IP过滤、sql语句黑名单、DBA平滑下线DB、从库流量配置、动态加载配置项。
项目的Github地址是https://github.com/Meituan-Dianping/DBProxy
sharding-JDBC
当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据库分库分表访问。
Sharding-JDBC是继dubbox和elastic-job之后,ddframe系列开源的第3个项目。
Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:
可适用于任何基于Java的ORM框架,如JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC。
可基于任何第三方的数据库连接池,如DBCP、C3P0、 BoneCP、Druid等。
理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持Oracle、SQLServer等数据库的计划。
Sharding-JDBC定位为轻量Java框架,使用客户端直连数据库,以jar包形式提供服务,无proxy代理层,无需额外部署,无其他依赖,DBA也无需改变原有的运维方式。
Sharding-JDBC分片策略灵活,可支持等号、between、in等多维度分片,也可支持多分片键。
SQL解析功能完善,支持聚合、分组、排序、limit、or等查询,并支持Binding Table以及笛卡尔积表查询。
35.我现在有一个未分库分表的系统,以后系统需分库分表,如何设计,让未分库分表的系统动态切换到分库分表的系统上?TCC? 那若出现网络原因,网络连不通怎么办啊?
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务节点上,分布式事务需要保证这些小操作要么全部成功,要么全部失败;本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
分布式系统事务要素 CAP
** 一致性:分布式环境下多个节点的数据是否强一致。
** 可用性:分布式服务能一直保证可用状态。当用户发出一个请求后,服务能在有限时间内返回结果。
** 分区容忍性:特指对网络分区的容忍性。
三者只能取其二,而且分区容忍性是不可或缺的
BASE 理论
核心思想:
** 基本可用(BasicallyAvailable):指分布式系统在出现故障时,允许损失部分的可用性来保证核心可用。
** 软状态(SoftState):指允许分布式系统存在中间状态,该中间状态不会影响到系统的整体可用性。
** 最终一致性(EventualConsistency):指分布式系统中的所有副本数据经过一定时间后,最终能够达到一致的状态。
一致性分类
** 强一致性:数据更新成功后,任意时刻所有副本中的数据都是一致的,一般采用同步的方式实现。
** 弱一致性:数据更新成功后,系统不承诺立即可以读到最新写入的值,也不承诺具体多久之后可以读到。
** 最终一致性:弱一致性的一种形式,数据更新成功后,系统不承诺立即可以返回最新写入的值,但是保证最终会返回上一次更新操作的值。
分布式事务解决方案:一般有以下几种
** 两阶段提交(2PC, Two-phase Commit)方案
强一致性
2PC的核心原理是通过提交分阶段和记日志的方式,记录下事务提交所处的阶段状态,在组件宕机重启后,可通过日志恢复事务提交的阶段状态,并在这个状态节点重试,如Coordinator重启后,通过日志可以确定提交处于Prepare还是PrepareAll状态,若是前者,说明有节点可能没有Prepare成功,或所有节点Prepare成功但还没有下发Commit,状态恢复后给所有节点下发RollBack;若是PrepareAll状态,需要给所有节点下发Commit,数据库节点需要保证Commit幂等。
** eBay 事件队列方案
最终一致性
它的核心思想是将需要分布式处理的任务通过消息或者日志的方式来异步执行,消息或日志可以存到本地文件、数据库或消息队列,再通过业务规则进行失败重试,它要求各服务的接口是幂等的。
** TCC 补偿模式
最终一致性
某业务模型由服务 A、服务B、服务C、服务D 共同组成的一个微服务架构系统。服务A 需要依次调用服务B、服务C 和服务D 共同完成一个操作。当服务A 调用服务D 失败时,若要保证整个系统数据的一致性,就要对服务B 和服务C 的invoke 操作进行回滚,执行反向的revert 操作。回滚成功后,整个微服务系统是数据一致的。
要求
** 服务调用链必须被记录下来。
** 必须按失败原因执行不同的回滚策略。
** 缓存数据最终一致性
在我们的业务系统中,缓存(Redis 或者Memcached)通常被用在数据库前面,作为数据读取的缓冲,使得I/O 操作不至于直接落在数据库上。以商品详情页为例,假如卖家修改了商品信息,并写回到数据库,但是这时候用户从商品详情页看到的信息还是从缓存中拿到的过时数据,这就出现了缓存系统和数据库系统中的数据不一致的现象。
解决方案:
为缓存数据设置过期时间。当缓存中数据过期后,业务系统会从数据库中获取数据,并将新值放入缓存。这个过期时间就是系统可以达到最终一致的容忍时间。更新数据库数据后同时清除缓存数据。数据库数据更新后,同步删除缓存中数据,使得下次对商品详情的获取直接从数据库中获取,并同步到缓存。
39.分布式寻址方式都有哪些算法 知道一致性hash吗?手写一下java实现代码??你若userId取摸分片,那我要查一段连续时间里的数据怎么办???
分布式哈希(DHT):每个节点只维护一部分路由;每个节点只存储一部分数据。从而实现整个网络中的寻址和存储。
普通的后端节点取模算法
一致性哈希算法:
DHT的一种实现。本质还是一个哈希算法。回想平时我们做负载均衡,按querystring签名对后端节点取模是最简单也是最常用的算法,但节点的增删后所造成的问题显而易见,原有的请求几乎都落不到同一台机器上。优化一点的是carp算法(用机器ip和querystring一起做hash,选取hash值最小的一台),只让1/n的数据受到影响。
一致性哈希,似乎最早提出是在分布式cache里面的,让节点震荡的时候,影响最小,以提高分布式cache的命中率。不过现在更多的应用在分布式存储和p2p系统里面。
一致性哈希也只是提出四个概念和原则,并没有提及具体实现:
//www.greatytc.com/p/e968c081f563
1、balance:哈希结果尽可能的平均分散到各个节点上,使得每个节点都能得到充分利用。
2、Monotonicity:上面也说了,如果是用签名取模算法,节点变更会使得整个网络的映射关系更改。如果是carp,会使得1/n的映射关系更改。一致性哈希的目标是节点变更,不会改变网络的映射关系。
3、spread:同一份数据,存储到不同的节点上,换言之就是系统冗余。一致性哈希致力于降低系统冗度。
4、load:负载分散,和balance其实是差不多的意思,不过这里更多是指数据存储的均衡,balance是指访的均衡。
40.如何解决分库分表主键问题有什么实现方案??
UUID
维护一个Sequence表
维护多个Sequence表 但是起始值和步长错开