认识NoSQL
SQL:
结构化(Structured)
关联的(Relational)
SQL查询
ACID
A(Atomicity):原子性
C(Consistency):一致性
I(Isolation):隔离性
D(Durability):持久性
- Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 [1]
NoSQL:
- 非结构化
- 无关联的
- 非SQL
- BASE
缓存穿透:
缓存穿透是指查询一条数据库和缓存都没有的一条数据,就会 一直查询数据库,对数据库的访问压力就会增大。
常见的2种解决方案:
缓存空对象
- 优点:简单实现,维护方便
- 缺点:
- 额外的内存消耗
- 可能造成短期的不一致
布隆过滤
- 优点:内存占用较少,没有多余的key
- 缺点:
- 实现复杂
- 存在误判可能
增强id的复杂度,避免被猜测id规律
做好数据的基础格式校验
加强用户权限校验
做好热点参数的限流
缓存穿透:
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力
解决方案:
- 给不同的Key的TTL添加随机值
- 利用Redis集群提高服务的可用性
- 给缓存业务添加降级限流策略
- 给业务添加多级缓存
缓存击穿:
缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击
解决方案:
- 互斥锁
- 逻辑过期
解决方案 | 优点 | 缺点 |
---|---|---|
互斥锁 | 没有额外的内存消耗 保证一致性 实现简单 |
县城需要等待,性能受影响 可能有死锁风险 |
逻辑过期 | 线程无需等待,性能较好 | 不保证一致性 有额外内存消耗 实现复杂 |
全局唯一ID生成策略:
UUID
UUID是指在一台机器在同一时间中生成的数字在所有机器中都是唯一的。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)
优点:
- 简单,代码方便
- 生成ID性能非常好,基本不会有性能问题,本地生成,没有网络消耗
- 全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对
缺点:
没有排序,无法保证趋势递增
UUID往往是使用字符串存储,查询的效率比较低
存储空间比较大,UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用,如果是海量数据库,就需要考虑存储量的问题
信息不安全,基于MAC地址生成UUID的算法可能会造成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置
传输数据量大,并且不可读
Redis自增
优点:
- 不依赖于数据库,灵活方便,且性能优于数据库
- 数字ID天然排序,对分页或者需要排序的结果很有帮助
缺点:
- 如果系统中没有Redis,还需要引入新的组件,增加系统复杂度
- 需要编码和配置的工作量比较大
- Redis是单线程的,若造成阻塞,则会引发高并发问题,需要处理好集群与主从关系
snowflake算法
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。生成的是一个64位的二进制正整数,然后转换成10进制的数。64位二进制数由如下部分组成:
* SnowFlake的结构如下(每部分用-分开):
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
* (1-10-10-10-10-10-1-5-5-12) (1-41-10-12)优点
- 简单高效,生成速度快
- 时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序递增
- 灵活度高,可以根据业务需求,调整bit位的划分,满足不同的需求
缺点
- 依赖机器的时钟,如果服务器时钟回拨,会导致重复ID生成
- 在分布式环境上,每个服务器的时钟不可能完全同步,有时会出现不是全局递增的情况
数据库自增
优点:
- 简单,代码方便,性能可以接受
- 数字ID天然排序,对分页或者需要排序的结果很有帮助
缺点:
- 不同数据库语法和实现不同,数据库迁移的时候或多数据库版本支持的时候需要处理
- 在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险
- 在性能达不到要求的情况下,比较难于扩展
- 如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦
- 分表分库的时候会有麻烦