【大数据存储复习笔记】

CAP理论:

一致性(Consistency):在分布式系统的所有数据备份中,在同一时刻是否有相同的值。(等同于所有的节点访问同一份最新的数据副本)

可用性(Available):在集群中的一部分节点故障后,集群整体是否还能相应客户端的读写请求。(对数据更新具有高可用性)

分区容忍性(Partation tolerance):对通信的时限要求,系统如果不能在一定时限内达成数据一致性,就必须分区。

CAwithoutP——放弃分区容忍性,例如:关系型数据库、LDAP

CPwithoutA——放弃可用性,例如传统数据库的分布式事务,分布式锁

APwithoutC——放弃最终一致性,例如NoSQL、DNS、Web缓存属于此类

负载均衡:

在服务器集群中,Nginx 起到一个反向代理服务器的作用。为了避免单独一个服务器压力过大导致服务器奔溃,就需要将不同用户的请求转发给不同给不同的服务器,保证集群中的每一台服务器都能正常运作,这种机制就叫做负载均衡。

负载均衡策略:

轮询(默认):round robin,轮询策略就是指每个请求会按时间顺序逐一分配到不同的后台服务器上。(轮询策略适合服务器配置相当,无状态且短平快的服务使用。)

最少连接:请求转发给连接数较少的后端服务器。前面的轮询策略是把请求平均地转发给集群中的每个后台服务器,使得它们的负载大致相同,但是有些请求可能占用的时间会很长,可能导致所在的后端负载过高。这种情况下选用least_conn策略就能达到 更好的负载均衡效果。(适合用在请求处理时间长短不一造成服务器过载的场景。)

IP 地址哈希:按照客户端的IP去分配服务器,使同一个客户端的请求都转发到同一个后台服务器,保证了Session的统一性,可以用来解决Session的跨域问题。

基于权重的负载均衡:在轮询策略的基础上,另外指定了轮询的几率。(权重策略可以与least_conn和ip_hash

结合使用。权重策略比较适合服务器的硬件配置差别较大的情况。)

一致性hash算法:

一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的 对象大部分集中缓存在某一台服务器上)问题。可以在服务器IP或主机名的后面增加编号(即每台主机计算多个虚拟节点)来解决。

缓存击穿、穿透、雪崩现象及解决办法

缓存穿透:指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。

解决方案:1.查询返回的数据为空,仍把这个空结果进行缓存,但过期时间会比较短;2.布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对 DB 的查询。

缓存击穿:对于设置了过期时间的 key,缓存在某个时间点过期的时候,恰好这时间点对这个 Key 有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。

解决方案:1.使用互斥锁:在第一个查询数据的请求上使用一个互斥锁来锁住它。其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。2.永远不过期:物理不过期,但逻辑过期(后台异步线程去刷新)。

缓存雪崩:设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到 DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key,击穿是某一个key 缓存。

解决方案:1.将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。2.构建多级缓存架构:nginx缓存+redis缓存+其他缓存((ehcache等)。

Redis的数据结构:

在这里插入图片描述

String:字符串类型是 Redis 中最基本的数据结构,它能存储任何类型的数据,包括二进制数据,序列化后的数据,JSON化的对象甚至是一张图片,最大 512M。包括3种值的类型:

– 字符串

– 整数

– 浮点数

应用场景:用来存储图片;统计微博书、统计粉丝数等。

List:列表对象,用于存储String序列。按照插入顺序排序,元素可以重复。你可以添加一个元素到列表的头部(左边)或者尾部(右边), 底层是个链表结构。

应用场景:List实现队列:消息排队和异步逻辑处理;文章列表或数据分页展示的应用。

Hash:Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。

应用场景:存储用户信息、分布式生成唯一 ID。

Set:String 类型的无序无重复集合。相当于Java 语言中的 HashSet,它内部的键值对是无序、唯一的。它的内部实现相当于一个特殊的字典,字典中所有的value 都是一个值 NULL。

应用场景:标签;去重,共同好友;随机化展示。

ZSet:Redis 有序集合zset和集合set一样也是string类型元素 的集合,且不允许重复的成员。不同的是zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。

应用场景:在首页推荐10个最热门的帖子,也就是阅读量由高到低,排行榜的实现等业务;IM中最近的会话列表。

Redis的持久化方式:

RDB:快照模式,Redis将内存中的所有数据全量写入到文件中 。它是 Redis 默认的数据持久化方式,它会将数据库的快照保存在 dump.rdb 这个二进制文件中。

• 优点:

– 每隔一段时间进行备份,全量备份 save 900 1 (900秒更新一次就触发RDB全量备份)

– 灾备简单,可以远程传输

– 备份是fork一个子进程,对当前进行数据访问主进程不影响

• 劣势

– 发生故障率时,有可能丢失最后一次备份的数据

– 子进程进行数据备份时会复制内存数据导致内存膨胀两倍,如果复制的数据量很⼤

大就会导致CPU和内存负载很高产生卡顿

AOF:被称为追加模式,或日志模式,是 Redis 提供的另一种持久化策略,它能够存储 Redis 服务器已经执行过的命令,并且只记录对内存有过修改的命令,这种数据记录方法,被叫做“增量复制”,其默认存储文件为appendonly.aof。

机制:以日志的形式来记录用户的请求写操作(特别像MySQL的binlog),

读操作不会保存;以追加的形式进行记录到appendonly.aof 这个文

件中;Redis的aof恢复其实就是把追加的文件从头到尾全部执行一

– 写入机制:内容不直接写入到磁盘,而是放到内存缓冲区,填满才落盘;

– 重写机制:长期运行,aof文件会越变越长。

在这里插入图片描述

Redis的内存回收机制:

redis占用内存分为键值对所耗内存和本身运行所耗内存两部分,可回收的部分只能是键值对所使用的内存。键值对内存的回收分以带过期的、不带过期的、热点数据、冷数据。

Redis 回收内存大致有两个机制:一是删除到达过期时间的键值对象;二是当内存达到 maxmemory 时触发内存移除控制策略,强制删除选择出来的键值对象。
一、实施过期删除的三种模式

• 定时删除(一 key 一定时器)

– 在设置键的过期时间的同时,创建定时器,让定时器在键过期时间到来时,即刻执行键值对的删除。

惰性删除

– 当客户端请求时,如果发现过期超时就进行删除并返回客户端一个nil

(主动)定期删除

– redis默认会一秒10次巡检内存,将已经过期的数据进行删除

– 可以设置主动频次:config get hz

二、内存达到 maxmemory时的数据淘汰策略(内存淘汰机制)

  1. voltile-lru 从已经设置过期时间的数据集中挑选最近最少使用的数据淘汰(在设置了过期时间的键空间中,移除最近最少使用的 key)
  2. voltile-ttl 从已经设置过期时间的数据库集当中挑选将要过期的数据
  3. voltile-random 从已经设置过期时间的数据集任意选择淘汰数据
  4. allkeys-lru 从数据集中挑选最近最少使用的数据淘汰
  5. allkeys-random 从数据集中任意选择淘汰的数据
  6. no-eviction 当内存不足以容纳新写入数据时,新写入操作会报错
  7. volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;
  8. allkeys-lfu:淘汰整个键值中最少使用的键值。

Redis的节点通信协议:

redis 客户端和服务端之间通信的协议是RESP(REdis Serialization Protocol)。传输层使用TCP。RESP的特点是:

  • 实现容易
  • 解析快
  • 人类可读

RESP实际上是一个支持以下数据类型的序列化协议:Redis命令(Inline Command),简单字符串(Simple String),错误(Error),整数(Integer),批量字符串(Bulk String)和数组(Array)。

RESP在Redis中用作请求 - 响应协议的方式如下:

  • 客户端将命令作为Inline Command或Bulk Strings类型的RESP数组发送到Redis服务器。
  • 服务器根据命令实现回复一种除Inline Command以外的RESP类型。

(1)Inline Command

格式:首字符为Redis命令名的字符 str1 str2 str3… 例如:EXISITS key1

(2)Simple String

格式:首字符为‘+’,最后以“\r\n”结束。

例如:“+OK\r\n” 表示“OK“这个string数据

(3)Bulk String

格式:首字符为‘$’,紧随其后的是string数据长度,然后数据以“\r\n”开始,最后以“\r\n”结束。

例如:“$12\r\nhello\r\nworld\r\n”表示”hello\r\nworld“这个两行的数据

(4)Error

格式:首字符为‘-’,最后以“\r\n”结束。

例如:“-ERROR unknown command’foobar’\r\n”表示一个error和它的错误信息。

(5)Integer

格式:首字符为‘:’,最后以“\r\n”结束。

例如:“:13\r\n”表示13这个整数。

(6)Array

格式:首字符为‘*****’,紧跟着数组的长度,“\r\n”之后是数组每个元素的序列化数据。

例如:“*2\r\n+abc\r\n:9\r\n”表示[“abc”,9]这个长度为2的数组。

Raft算法:

参考:https://www.cnblogs.com/xybaby/p/10124083.html#_label_0

通过 leader,raft 将一致性问题分解成三个相对独立的子问题:

Leader Election

raft协议中,一个节点任一时刻处于以下三个状态之一:

  • leader
  • follower
  • candidate

当集群启动或者 leader 失效时必须选出一个新的leader,步骤如下:

  • 增加节点本地的 current term ,切换到candidate状态
  • 投自己一票
  • 并行给其他节点发送 RequestVote RPCs
  • 等待其他节点的回复

Log Replication

leader 必须接收客户端提交的日志,并将其复制到集群中的其他节点,强制其他节点的日志与 leader 一样。

客户端的一切请求来发送到leader,leader来调度这些并发请求的顺序,并且保证leader与followers状态的一致性。raft中的做法是,将这些请求以及执行顺序告知followers。leader和followers以相同的顺序来执行这些请求,保证状态一致。相同的初识状态 + 相同的输入 = 相同的结束状态

Safety:最关键的安全点就是图3.2中的 State Machine Safety Property。如果任何一个 server 已经在它的状态机apply了一条日志,其他的 server 不可能在相同的 index 处 apply 其他不同的日志条目。后面将会讲述 raft 如何实现这一点。

  • safety:nothing bad happens,
  • liveness: something good eventually happens.

在任何系统模型下,都需要满足safety属性,即在任何情况下,系统都不能出现不可逆的错误,也不能向客户端返回错误的内容。比如,raft保证被复制到大多数节点的日志不会被回滚,那么就是safety属性。而raft最终会让所有节点状态一致,这属于liveness属性。

为了在任何异常情况下系统不出错,即满足safety属性,对leader election,log replication两个子问题有诸多约束

leader election约束:

  • 同一任期内最多只能投一票,先来先得
  • 选举人必须比自己知道的更多(比较term,log index)

log replication约束:

  • 一个log被复制到大多数节点,就是committed,保证不会回滚
  • leader一定包含最新的committed log,因此leader只会追加日志,不会删除覆盖日志
  • 不同节点,某个位置上日志相同,那么这个位置之前的所有日志一定是相同的
  • Raft never commits log entries from previous terms by counting replicas.

关系型数据库和非关系型数据库的优缺点:

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织。

优点:

1、易于维护:都是使用表结构,格式一致;

2、使用方便:SQL语言通用,可用于复杂查询;

3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。

缺点:

1、读写性能比较差,尤其是海量数据的高效率读写;

2、固定的表结构,灵活度稍欠;

3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

优点:

1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。

2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;

3、读写性能高:无需经过sql的解析

4、高扩展性;

5、成本低:nosql数据库部署简单,基本都是开源软件。

缺点:

1、不提供sql支持,学习和使用成本较高;

2、无事务处理;

3、数据结构相对复杂,复杂查询方面稍欠。

非关系型数据库的分类和比较:

1、文档型

2、key-value型

3、列式数据库

4、图形数据库

在这里插入图片描述

Redis优化:

内存优化

(1)采用压缩数据结构作为值的底层实现(如:ziplist、quicklist和intset等):1)Redis只支持压缩编码格式向非压缩编码格式转化(重启可实现逆转换);2)当使用压缩编码格式时不建议频繁增删操作,非常消耗CPU;

(2)降低Redis的外层键数量(使用多层数据结构的类型存储类似数据):1)建议使用哈希表实现(底层应为ziplist,否则可能消耗更多的内存);2)ziplist长度需控制在1000以内(读取长列表非常消耗CPU);3)仅适用于存储小对象;

缓存优化

实现Redis在应用中充当缓存层的实时性、高效性和高可用性

1)实际应用中将Redis做为底层存储层(数据库)的缓存层;

配置优化:通过配置Linux系统提升Redis性能

1)Redis是CPU密集型服务,不建议和其他多核CPU密集型服务部署在一起

2)若Redis开启持久化或参数赋值,则不建议绑定CPU(子进程消耗过大)

3)建议所有运行Redis节点的Linux运行NTP服务(确保时间一致性)

4)关闭swap或降低其优先级(同时保证系统有20~30%闲置内存)

//不和其他CPU密集型服务部署在一起是为避免CPU过度竞争
优化内存占用

(1)使用整型/长整型代替字符串

(2)利用共享对象减少对象的创建(同时减少了redisObject的创建),节省内存空间。目前redis中的共享对象只包括10000个整数(0-9999);可以通过调整REDIS_SHARED_INTEGERS参数提高共享对象的个数;

(3)缩短键值对的存储长度

基于内存淘汰机制的优化:

(1)设置键值的过期时间(惰性删除):根据实际的业务情况,对键值设置合理的过期时间,这样 Redis 会帮你自动清除过期的键值对,以节约对内存的占用,以避免键值过多的堆积,频繁的触发内存淘汰策略。

(2)限制 Redis 内存大小(重点):在 64 位操作系统中 Redis 的内存大小是没有限制的,也就是配置项 maxmemory 是被注释掉的,这样就会导致在物理内存不足时,使用 swap 空间既交换空间,而当操心系统将 Redis 所用的内存 分页移至 swap 空间时,将会阻塞Redis 进程,导致 Redis 出现延迟,从而影响 Redis 的整体性 能。因此我们需要限制 Redis 的内存大小为一个固定的值,当Redis 的运行到达此值时会触发内存淘汰策略

实现通用缓存框架需要实现的大致功能:

​ 1、提供统一的缓存操作api;

​ 2、支持同时使用多种缓存实现;

​ 3、提供灵活的配置;

​ 4、需要防止缓存穿透;

​ 5、需要可以灵活指定缓存存活时间;

​ 6、需要任意控制缓存的停用或启用。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值