数据库相关
Mybatis的优缺点
优点:
- 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签, 支持编写动态 SQL 语句, 并可重用。
- 与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;
- 很好的与各种数据库兼容( 因为 MyBatis 使用 JDBC 来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持)。
- 能够与 Spring 很好的集成;
- 提供映射标签, 支持对象与数据库的 ORM 字段关系映射; 提供对象关系映射标签, 支持对象关系组件维护。
缺点:
- SQL 语句的编写工作量较大, 尤其当字段多、关联表多时, 对开发人员编写SQL 语句的功底有一定要求。
- SQL 语句依赖于数据库, 导致数据库移植性差, 不能随意更换数据库。
#{}和${}的区别是什么?
#{}是预编译处理、是占位符, ${}是字符串替换、是拼接符。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用 PreparedStatement 来赋值;
Mybatis在处理${}时,会将sql中的${}替换成变量的值,调用 Statement 来赋值;
使用#{}可以有效的防止 SQL 注入, 提高系统安全性。
索引的基本原理
索引用来快速地寻找那些具有特定值的记录。如果没有索引,一般来说执行查询时遍历整张表。
索引的原理:就是把无序的数据变成有序的查询
- 把创建了索引的列的内容进行排序
- 对排序结果生成倒排表
- 在倒排表内容上拼上数据地址链
- 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
索引设计的原则?
查询更快、占用空间更小
- 适合索引的列是出现在where子句中的列,或者连接子句中指定的列
- 基数较小的表,索引效果较差,没有必要在此列建立索引
- 使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间,如果搜索词超过索引前缀长度,则使用索引排除不匹配的行,然后检查其余行是否可能匹配。
- 不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。
- 定义有外键的数据列一定要建立索引。
- 更新频繁字段不适合创建索引
- 若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)
- 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
- 对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。
- 对于定义为text、image和bit的数据类型的列不要建立索引。
事务的基本特性和隔离级别
事务基本特性ACID分别是:
原子性指的是一个事务中的操作要么全部成功,要么全部失败。
一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。
隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。并发事务互不干扰,确保事务独立执行。
持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中。在数据库中,隔离级别用于定义并发事务之间的交互程度,特别是如何处理事务执行过程中对数据的访问和修改。不同的隔离级别会影响到事务的并发性和数据一致性。
● read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。 用户本来应该读取到id=1的用户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。
● read commit 读已提交,两次读取结果不一致,叫做不可重复读。 不可重复读解决了脏读的问题,他只会读取已经提交的事务。 用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。
● repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都一样,但是有可能产生幻读。
● serializable 串行,一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。
什么是MVCC
MVCC(Multi-Version Concurrency Control,多版本并发控制) 是一种用于数据库管理系统的并发控制机制,旨在提高数据库的并发性能,同时避免读写冲突。MVCC 的核心思想是通过维护数据的多个版本来实现并发访问,而不是通过加锁来阻塞其他操作。
MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD、REPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程。可以使不同事务的读-写、写-读操作并发执行,从而提升系统性能。
简述MyISAM和InnoDB的区别
MyISAM 和 InnoDB 是 MySQL 中常用的两种存储引擎
MyISAM:
●不支持事务,但是每次查询都是原子的;
●支持表级锁,即每次操作是对整个表加锁;
●存储表的总行数;
●一个MYISAM表有三个文件:索引文件、表结构文件、数据文件;
●采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
InnoDb:
●支持ACID的事务,支持事务的四种隔离级别;
●支持行级锁及外键约束:因此可以支持写并发;
●不存储总行数;
●一个InnoDb引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为2G),受操作系统文件大小的限制;
●主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整。
索引覆盖是什么
索引覆盖(Index Covering) 是指在数据库查询过程中,查询所需的所有数据都可以通过索引来获取,而无需访问表的实际数据行。
也就是说,查询可以通过仅扫描索引(而不访问表数据)来返回结果,从而提高查询性能。
覆盖索引与常规索引的对比
- 常规索引:查询时,数据库首先使用索引来定位数据行的位置,然后通过回表操作从数据表中读取完整的行数据。
- 覆盖索引:查询时,所有需要的数据都可以从索引本身中获取,不需要回表,从而提高查询性能。
最左前缀原则是什么
当一个SQL想要利用索引是,就一定要提供该索引所对应的字段中最左边的字段,也就是排在最前面的字段,比如针对a,b,c三个字段建立了一个联合索引,那么在写一个sql时就一定要提供a字段的条件,这样才能用到联合索引,这是由于在建立a,b,c三个字段的联合索引时,底层的B+树是按照a,b,c三个字段从左往右去比较大小进行排序的,所以如果想要利用B+树进行快速查找也得符合这个规则
Innodb是如何实现事务的
Innodb通过Buffer Pool,LogBuffer,Redo Log,Undo Log来实现事务,以一个update语句为例:
- Innodb在收到一个update语句后,会先根据条件找到数据所在的页,并将该页缓存在Buffer Pool中
- 执行update语句,修改Buffer Pool中的数据,也就是内存中的数据
- 针对update语句生成一个RedoLog对象,并存入LogBuffer中
- 针对update语句生成undolog日志,用于事务回滚
- 如果事务提交,那么则把RedoLog对象进行持久化,后续还有其他机制将Buffer Pool中所修改的数据页持久化到磁盘中
- 如果事务回滚,则利用undolog日志进行回滚
B树和B+树的区别,为什么Mysql使用B+树
B树的特点:
- 内部节点存储数据和索引:B树的每个节点包含数据和指向子节点的指针,叶子节点和非叶子节点都能存储数据。
- 插入和删除:在 B 树中,插入和删除时需要进行内部节点的调整,可能会影响树的结构。
B+树的特点:
- 数据仅存储在叶节点:B+树中的数据只存储在叶节点,内部节点只保存索引(指向子节点的指针)。这样,内部节点的大小通常比 B 树小。
- 叶节点通过链表连接:B+树的叶节点之间通过链表连接,形成一个有序的数据链表,方便顺序遍历。
- 所有节点指向叶节点:B+树的查询从根节点开始,最终都会到达叶节点,所有的数据都在叶节点中,这提高了查找效率。
MySQL 使用 B+树 主要是因为它具有以下优势:
高效的范围查询:B+树的叶节点通过链表连接,支持快速的顺序遍历,特别适合进行范围查询(比如
BETWEEN
、> <
等)。数据集中在叶节点:所有数据都存储在叶节点中,非叶节点仅存储索引,这样减少了内存的使用和提高了查询效率。
查询一致性:所有查询最终都访问叶节点,路径长度一致,查找过程更加稳定和高效。
顺序扫描性能好:B+树的叶节点是有序的,顺序扫描时非常高效,特别适合做
ORDER BY
或GROUP BY
操作。综上,B+树适合 MySQL 的查询和索引需求,特别是在处理大量数据时,它提供了更高的性能和更低的资源消耗。
Mysql锁有哪些,如何理解
按锁粒度分类:
- 行锁:锁某行数据,锁粒度最小,并发度高
- 表锁:锁整张表,锁粒度最大,并发度低
- 间隙锁:锁的是一个区间
还可以分为:
共享锁:也就是读锁,一个事务给某行数据加了读锁,其他事务也可以读,但是不能写
排它锁:也就是写锁,一个事务给某行数据加了写锁,其他事务不能读,也不能写还可以分为:
乐观锁:并不会真正的去锁某行记录,而是通过一个版本号来实现的
悲观锁:上面所的行锁、表锁等都是悲观锁
Mysql慢查询该如何优化?
- 检查是否走了索引,如果没有则优化SQL利用索引
- 检查所利用的索引,是否是最优索引
- 检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据
- 检查表中数据是否过多,是否应该进行分库分表了
- 检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源
count(*)与count(1)有什么区别
Redis
什么是RDB和AOF
什么是RDB和AOF-CSDN博客
RDB(Redis 数据库持久化) 和 AOF(Append-Only File) 是 Redis 提供的两种持久化机制,用于确保数据在 Redis 重启后能够恢复。它们分别有不同的工作原理和优缺点,可以根据具体需求选择合适的方式进行持久化。
RDB:Redis DataBase,在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
优点:
- 整个Redis数据库将只包含一个文件 dump.rdb,方便持久化。
- 容灾性好,方便备份。
- 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
- 相对于数据集大时,比 AOF 的启动效率更高。
缺点:
- 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
- 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
AOF:Append Only File,以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录
优点:
- 数据安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。
- 通过 append 模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redis-check-aof 工具解决数据一致性问题。
- AOF 机制的 rewrite 模式。定期对AOF文件进行重写,以达到压缩的目的
缺点:
- AOF 文件比 RDB 文件大,且恢复速度慢。
- 数据集大的时候,比 rdb 启动效率低。
- 运行效率没有RDB高
AOF文件比RDB更新频率高,优先使用AOF还原数据,AOF比RDB更安全也更大,RDB性能比AOF好,如果两个都配了优先加载AOF。
Redis的过期键的删除策略
Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。
●惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
●定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
Redis中同时使用了惰性过期和定期过期两种过期策略。
简述Redis事务实现
简述Redis事务实现-CSDN博客
在 Redis 中,事务是一组被作为一个单元执行的命令集合。与传统的关系型数据库事务不同,Redis 的事务没有提供像 回滚 或 提交 这样的功能,但它依然通过一些机制确保命令的原子性。
Redis 事务的基本实现方式是通过 MULTI、EXEC、DISCARD 和 WATCH 等命令来控制。以下是 Redis 事务的核心机制:
1. MULTI
- 使用
MULTI
命令来开始一个事务。执行MULTI
后,Redis 会进入一个事务块模式,此时所有的命令都会被入队,并不会立即执行。- 所有在事务中的命令都会被放入一个队列中,直到执行
EXEC
命令时,才会按顺序执行。2. 命令入队
- 在
MULTI
命令之后,后续的 Redis 命令(例如SET
、INCR
、DEL
等)不会立即执行,而是被放入事务队列中等待。- 每个命令会被当作一个普通的命令进行入队,不会检查是否有错误,也不会执行(即使命令有语法错误,也不会立即反馈)。
3. EXEC
- 使用
EXEC
命令来执行事务中的所有命令。执行EXEC
时,Redis 会按顺序执行所有入队的命令,并返回执行结果。- 原子性:事务中的所有命令要么全部执行成功,要么在
EXEC
时统一执行,不会中途被其他命令打断。这确保了事务的原子性。4. DISCARD
- 使用
DISCARD
命令可以放弃当前事务,撤销事务中的所有命令。如果调用了DISCARD
,事务中的命令不会被执行,Redis 会返回 OK。5. WATCH
WATCH
命令用于监视一个或多个键。如果这些键在事务执行前发生变化(被其他客户端修改),则EXEC
命令会返回一个空数组,表示事务失败。- 这种机制类似于乐观锁,确保事务在执行时数据不会发生冲突,避免了脏数据。
事务的执行流程
- 客户端执行
MULTI
开启事务。- 客户端接着执行多条 Redis 命令,这些命令都会进入事务队列。
- 客户端执行
EXEC
提交事务,Redis 按顺序执行事务队列中的所有命令。- 如果在事务中使用了
WATCH
命令,Redis 会监视指定的键。如果在MULTI
和EXEC
之间的某个时刻,监视的键被修改,EXEC
会返回空数组,表示事务执行失败。
Redis 主从复制的核心原理
Redis 主从复制(Master-Slave Replication)是 Redis 提供的一个重要功能,允许一个 Redis 实例作为主节点(Master),将数据同步到一个或多个从节点(Slave)。通过主从复制,Redis 可以实现数据的冗余备份、负载均衡和高可用性。
Redis 主从复制的核心原理-CSDN博客
Redis 主从复制的核心原理是通过 异步复制 实现主节点与从节点之间的数据同步。从节点在连接到主节点后,会执行全量同步和增量同步来保证数据一致性。尽管复制是异步的,但在大多数情况下,Redis 能够高效地实现数据备份、负载均衡和高可用性。
Redis分布式锁底层是如何实现的?
Redis 分布式锁是一种基于 Redis 实现的分布式同步机制,用于在分布式系统中确保多个进程或线程对共享资源的互斥访问。Redis 分布式锁的底层实现通常依赖于 Redis 的原子操作和过期时间机制。
- 首先利用setnx来保证:如果key不存在才能获取到锁,如果key存在,则获取不到锁
- 然后还要利用lua脚本来保证多个redis操作的原子性
- 同时还要考虑到锁过期,所以需要额外的一个看门狗定时任务来监听锁是否需要续约
- 同时还要考虑到redis节点挂掉后的情况,所以需要采用红锁的方式来同时向N/2+1个节点申请锁,都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到
Redis分布式锁底层是如何实现的?-CSDN博客
Redis有哪些数据结构?分别有哪些典型的应用场景?
Redis的数据结构有:
- 字符串:可以用来做最简单的数据,可以缓存某个简单的字符串,也可以缓存某个json格式的字符串,Redis分布式锁的实现就利用了这种数据结构,还包括可以实现计数器、Session共享、分布式ID
- 哈希表:可以用来存储一些key-value对,更适合用来存储对象
- 列表:Redis的列表通过命令的组合,既可以当做栈,也可以当做队列来使用,可以用来缓存类似微信公众号、微博等消息流数据
- 集合:和列表类似,也可以存储多个元素,但是不能重复,集合可以进行交集、并集、差集操作,从而可以实现类似,我和某人共同关注的人、朋友圈点赞等功能
- 有序集合:集合是无序的,有序集合可以设置顺序,可以用来实现排行榜功能
Redis集群策略
Redis提供了三种集群策略:
- 主从模式:这种模式比较简单,主库可以读写,并且会和从库进行数据同步,这种模式下,客户端直接连主库或某个从库,但是但主库或从库宕机后,客户端需要手动修改IP,另外,这种模式也比较难进行扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能支持特大数据量
- 哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕机,然后在从库中选择一个库作为进的主库,另外哨兵也可以做集群,从而可以保证但某一个哨兵节点宕机后,还有其他哨兵节点可以继续工作,这种模式可以比较好的保证Redis集群的高可用,但是仍然不能很好的解决Redis的容量上限问题。
- Cluster模式:Cluster模式是用得比较多的模式,它支持多主多从,这种模式会按照key进行槽位的分配,可以使得不同的key分散到不同的主节点上,利用这种模式可以使得整个集群支持更大的数据容量,同时每个主节点可以拥有自己的多个从节点,如果该主节点宕机,会从它的从节点中选举一个新的主节点。
对于这三种模式,如果Redis要存的数据量不大,可以选择哨兵模式,如果Redis要存的数据量大,并且需要持续的扩容,那么选择Cluster模式。
缓存穿透、缓存击穿、缓存雪崩分别是什么
缓存中存放的大多都是热点数据,目的就是防止请求可以直接从缓存中获取到数据,而不用访问Mysql。
- 缓存雪崩:如果缓存中某一时刻大批热点数据同时过期,那么就可能导致大量请求直接访问Mysql了,解决办法就是在过期时间上增加一点随机值,另外如果搭建一个高可用的Redis集群也是防止缓存雪崩的有效手段
- 缓存击穿:和缓存雪崩类似,缓存雪崩是大批热点数据失效,而缓存击穿是指某一个热点key突然失效,也导致了大量请求直接访问Mysql数据库,这就是缓存击穿,解决方案就是考虑这个热点key不设过期时间
- 缓存穿透:假如某一时刻访问redis的大量key都在redis中不存在(比如黑客故意伪造一些乱七八糟的key),那么也会给数据造成压力,这就是缓存穿透,解决方案是使用布隆过滤器,它的作用就是如果它认为一个key不存在,那么这个key就肯定不存在,所以可以在缓存之前加一层布隆过滤器来拦截不存在的key
缓存穿透、缓存击穿、缓存雪崩分别是什么-CSDN博客
Redis和Mysql如何保证数据一致
- 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不一致
- 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中,这种方案能解决1方案的问题,但是在高并发下性能较低,而且仍然会出现数据不一致的问题,比如线程1删除了Redis缓存数据,正在更新Mysql,此时另外一个查询再查询,那么就会把Mysql中老数据又查到Redis中
- 延时双删,步骤是:先删除Redis缓存数据,再更新Mysql,延迟几百毫秒再删除Redis缓存数据,这样就算在更新Mysql时,有其他线程读了Mysql,把老数据读到了Redis中,那么也会被删除掉,从而把数据保持一致
Redis的持久化机制
Redis的持久化机制-CSDN博客
Redis单线程为什么这么快
Redis 单线程的高性能主要源于以下几个方面:
- 避免上下文切换和锁竞争:没有线程切换和锁竞争,减少了系统开销。
- 事件驱动模型:使用 I/O 多路复用(如 epoll/select)处理多个客户端请求,提升并发能力。
- 内存存储和优化数据结构:所有数据存储在内存,操作简单且数据结构高效(如哈希表、跳表)。
- 简化并发模型:单线程避免了多线程的复杂性和同步开销。
- 内存管理优化:通过内存池等技术减少内存碎片,提升访问速度。
什么是CAP理论
CAP 理论(CAP Theorem)是分布式系统中的一个基本理论,由计算机科学家 Eric Brewer 提出的。它描述了在一个分布式系统中,一致性(Consistency)、**可用性(Availability)和分区容忍性(Partition Tolerance)**三者之间的关系。
CAP 理论的核心观点是:在一个分布式系统中,最多只能同时满足这三者中的两个,而不能同时满足全部三个。
CAP 定理
CAP 理论表明,在发生分区时(网络故障或节点之间的连接丢失),系统必须在 一致性 和 可用性 之间做出权衡。具体来说,系统只能选择以下两个特性来保证:
- CA(Consistency + Availability):系统在没有网络分区的情况下保证一致性和可用性。但一旦出现分区,系统就不能继续正常运行。
- CP(Consistency + Partition Tolerance):系统在网络分区发生时仍然保持一致性和分区容忍性,但在此情况下可能无法保证可用性。
- AP(Availability + Partition Tolerance):系统在网络分区发生时保持可用性和分区容忍性,但无法保证一致性。
现实中的应用:
- CA 系统:适用于网络分区不常见,系统较为简单且不容易发生故障的场景。
- CP 系统:例如 HBase,通常在面对网络分区时会选择放弃可用性,保证数据一致性。
- AP 系统:如 Cassandra、MongoDB,在网络分区时会放弃一致性,确保系统仍然能响应请求。
总结:CAP 定理揭示了分布式系统设计中的基本取舍。选择一致性、可用性和分区容忍性之间的平衡,取决于系统的需求和应用场景。
什么是BASE理论
由于不能同时满足CAP,所以出现了BASE理论:
- BA:Basically Available,表示基本可用,表示可以允许一定程度的不可用,比如由于系统故障,请求时间变长,或者由于系统故障导致部分非核心功能不可用,都是允许的
- S:Soft state:表示分布式系统可以处于一种中间状态,比如数据正在同步
- E:Eventually consistent,表示最终一致性,不要求分布式系统数据实时达到一致,允许在经过一段时间后再达到一致,在达到一致过程中,系统也是可用的
什么是RPC
RPC,表示远程过程调用,对于Java这种面试对象语言,也可以理解为远程方法调用,RPC调用和HTTP调用是有区别的,RPC表示的是一种调用远程方法的方式,可以使用HTTP协议、或直接基于TCP协议来实现RPC,在Java中,我们可以通过直接使用某个服务接口的代理对象来执行方法,而底层则通过构造HTTP请求来调用远端的方法,所以,有一种说法是RPC协议是HTTP协议之上的一种协议,也是可以理解的。
数据一致性模型有哪些
●强一致性:当更新操作完成之后,任何多个后续进程的访问都会返回最新的更新过的值,这种是对用户 最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP理论,这种实现需要牺牲可用性。
●弱一致性:系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后 可以读到。用户读到某一操作对系统数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。
●最终一致性:最终一致性是弱一致性的特例,强调的是所有的数据副本,在经过一段时间的同步之后, 最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而 不需要实时保证系统数据的强一致性。到达最终一致性的时间 ,就是不一致窗口时间,在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。最终一致性模型根据其提供的不同保证可以划分为更多的模型,包括因果一致性和会话一致性等。
分布式ID是什么?有哪些解决方案?
在开发中,我们通常会需要一个唯一ID来标识数据,如果是单体架构,我们可以通过数据库的主键,或直接在内存中维护一个自增数字来作为ID都是可以的,但对于一个分布式系统,就会有可能会出现ID冲突,此时有以下解决方案:
- uuid:这种方案复杂度最低,但是会影响存储空间和性能
- mysql:利用单机数据库的自增主键,作为分布式ID的生成器,复杂度适中,ID长度较之uuid更短,但是受到单机数据库性能的限制,并发量大的时候,此方案也不是最优方案
- redis、zookeeper:比如redis的自增命令、zookeeper的顺序节点,这种方案和单机数据库(mysql)相比,性能有所提高,可以适当选用
- 雪花算法:一切问题如果能直接用算法解决,那就是最合适的,利用雪花算法也可以生成分布式ID,底层原理就是通过某台机器在某一毫秒内对某一个数字自增,这种方案也能保证分布式架构中的系统id唯一,但是只能保证趋势递增。业界存在tinyid、leaf等开源中间件实现了雪花算法。