大数据存储技术期末复习(自用)

Posted St Clair

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据存储技术期末复习(自用)相关的知识,希望对你有一定的参考价值。

一、题型

1. 判断题(20*2)

2. 简答题(3个*10)

3. 设计题(2个*15)

二、往年题目

三、知识点

(1)CAP理论

1、定义

一致性C:所有数据备份在同一时刻的值相同。读写请求是原子、串行的。

可用性A:部分节点故障,但整体仍然能响应读写请求。请求时间是有限、可终止的。

分区容忍性P:在一定通信时限内达成数据一致,否则发生分区,即部分节点无法和其他节点进行通信。分区是无法避免的。

2、分类

CA:关系型/单点数据库、LDAP、RDBMS,分区后子系统保持CA。

CP:传统数据库分布式事务/分布式数据库、分布式锁、MongoDB、HBase、Redis

AP:DNS、Web缓存、NOSQL、Couch DB、Riak、Cassandra、Dynamo DB。分区节点失联导致数据不一致。

3、注意

没有一个软件系统同时满足CAP:这里的C 指的是强一致性。针对分布式系统而言,一定满足P,即存在网络分区(网络延时)。反证法,允许P-则Server丢包-则C不一致-CAP不成立。

弱一致性:最终一致性,DNS,Gossip (Cassandra的通信协议)

强一致性:同步,Paxos,Raft (multi-paxos),ZAB (multi-paxos)

(2)强一致性算法-paxos

1、共识算法

相同的初识状态+ 相同的输入 = 相同的结束状态。如mysql 的 binlog,paxos。

2、强一致性算法

强一致性算法=共识算法+client行为。强一致性算法强调多数派,读写需要大于N/2个节点,属于并发环境下的顺序问题。

3、强一致性算法-paxos:

角色:

Client:系统外部角色,请求发起者,比如民众

Proposer:接受client请求,向集群提出提案(propose)。并在冲突发生时,起到冲突调节的作用。像议员,替民众提出议案。

Acceptor(Voter):提议投票和接收者,只有在形成法定人数(Quorum,一般即为majority多数派)时,提议才会最终被接受。像国会。

Learner:提议接受者,backup,备份节点,对集群一致性没什么影响。

步骤阶段:

(3)强一致性算法-Raft

1、三个角色

领导者:0/1个,发送心跳消息,处理客户端读写请求,管理日志复制等。

候选人:领导者心跳超时,发起投票请求,当选领导者。

选民:处理日志消息,等待心跳消息,如果领导超时,就推举自己成为候选。

2、任期

递增,逻辑时钟选举投票以及日志复制的重要依据。

3、过程

候选人向选民提出选举自己的请求,超过n/2同意,即可成为领导,进行日志复制等操作,宕机后超时时间最短的选民成为新的候选者,发起新一轮选举,重复以上步骤。

可以看出所有节点启动时都是follower状态;在一段时间内如果没有收到来自leader的心跳,从follower切换到candidate,发起选举;如果收到majority的赞成票(含自己的一票)则切换到leader状态;如果发现其他节点比自己更新,则主动切换到follower。总之,系统中最多只有一个leader,如果在一段时间里发现没有leader,则大家通过选举-投票选出leader。leader会不停的给follower发心跳消息,表明自己的存活状态。如果leader故障,那么follower会转换成candidate,重新选出leader。

4、三个问题:选举,日志复制,安全

日志:Raft 数据的载体,数据存储的最小单位。

日志结构:用户指令、任期、索引

日志复制:复制状态机-共识、日志、状态机。 mysql 的 HA 架构、redis 的集群架构。

日志同步:二阶段提交2PC。提交放到下一次请求,减少请求次数。

日志一致性:根据任期编号和索引值确定要不要复制

选举规则:自荐,少数服从多数,强者优先,每人一票先到先得,禁止造反,终身责任制。

强者优先:候选者任期编号大于自己,候选者日记完整性高于自己,才会投票。

(4)nginx的负载均衡策略

IP地址哈希:根据IP地址分配,同一个客户端请求转发给同一个服务器,保证session一致性,适合解决跨域问题。

(5)一致性Hash算法

Hash环:整个哈希值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织,0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环

Hash取模:Node A,B,C,D四台机器,利用其 IP 地址进行hash取模。体现了单调性--原有内容映射到原缓冲。将数据key使用相同的Hash函数计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”(步数编号),第一台遇到的服务器就是其应该定位到的服务器!

容错性/可扩展性:Node C 宕机,增加一台机器Node X,仅仅影响Node C到环空间的前一台服务器(逆时针第一台)之间的数据。因此,一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据(这之间的失效了),具有较好的容错性和可扩展性。

Hash环的数据倾斜问题、负载均衡:服务节点太少时,容易因为节点分布不均匀而造成数据倾斜。改进:引入虚节点,可以在服务器IP或主机名的后面增加编号,个数远大于当前节点数,均匀分布到一致性哈希值域环,提高缓冲空间利用率。

(6)全局ID生成算法

1、全局ID特点:

唯一-避免id冲突、在表合并迁移的时候,

有序,

可用-高并发正确,

自主-不依赖中心认证,

安全-不泄露信息。

2、UUID:当前日期时间+时钟序列+唯一硬件识别号。

优点:API简单易用。

缺点:内存大(超长字符串)、字符串不能加工、可读性差。

3、ID生成表模式:

机制:采用MySQL自增长ID机制,如: Mysql的auto_increment(自动 定量增长)。

优点:简单、天然有序

缺点:并发性不好(只能一个写);数据库写压力大(就一个在写);数据库故障后不可使用(就一个增长列);存在泄露风险(就一个)。

改进:

a.水平拆分:每个数据库设置不同的初始值和相同的自增步长

b.批量缓存自增ID,优点:可以避免固定步长带来的扩容问题(多条路,不必一直扩);缺点:服务器重启、单点故障会造成ID不连续(少了几个,就不连续了)。

4、Snowflake算法:

5、结合缓存方案:利用ID生成表模式成批获取ID放入本地缓存。

优点:高性能、低延迟、有序。

缺点:不连贯

6、Redis 生成ID:

定义:单线程操作,自增原子命令,保证ID 唯一有序。

优点:① 不依赖于数据库,灵活方便,且性能优于数据库。② 数字ID天然有序

缺点:① 系统需要引入Redis的组件,增加系统复杂度。② 编码配置的工作量大。

优化方案:单节点性能瓶颈,因此使用Redis 集群来获取更高的吞吐量,并利用(①数据库水平拆分 ②批量缓存自增ID)来配置集群。

应用场景:生成每天从0开始的流水号。比如:“订单号=日期+当日自增长号”,则可以每天在Redis中生成一个Key,使用INCR进行累加。

7、Mongo的objectld算法

定义:使用12字节(24bit)的BSON 类型字符串作为ID,并将所占的24bit 划分成多段。

ID:新版ObjectId中“机器标识码+进程号” 改为用随机数作为机器标识和进程号的值。

(7)设计一个缓存框架(参考课本java或者课件项目golang都可以)

通过JSR107规范,将缓存框架定义为客户端层、缓存提供层、缓存管理层、缓存存储层。其中缓存存储层又分为基本存储层、LRU存储层和Weak存储层。

缓存框架基本结构如下

缓存框架的介绍说明

客户端层:使用者直接通过该层与数据进行交互,从数据源(文件,数据库等)获取数据并添加到缓存中。要注意的是客户端层不应该支持多种数据源的配置,其一是因为数据源的种类太多,没办法实现;其二是扩展性不好。

缓存提供层:主要对缓存管理层的生命周期进行维护,负责缓存管理层的创建、保存、获取以及销毁。通过CachingProvider类创建缓存提供层对象。

缓存管理层:对应接口类CacheManager所对应的正是缓存管理层,在缓存框架中CacheManager的实现类,主要负责管理多个Cache实例,对Cache实例的生命周期进行维护,负责Cache实例的创建、保存、获取以及销毁。

Cache实例的创建和获取实际上主要是基于一个缓存池来实现的,在代码中使用的是一个ConcurrentHashMap类,可以根据多个不同的Cache名称创建多个缓存实例,从而可以并发的读取。

缓存存储层:主要负责缓存数据的存储和缓存的淘汰机制,基于DataStore接口实现,其中包含三个实现类:BaseDataStore、LRUDataStore、WeakDataStore。通过key值以及get、put、remove、replace方法可以获取、增加、删除、替换缓存数据。

基本存储层:是以普通的ConcurrentHashMap为存储核心,数据不淘汰。

LRU存储层:‘最近最少用’为原则,是一种相对平衡的一种淘汰算法。LRU 算法最核心的 2 个数据结构是:字典(map),存储键和值的映射关系;双向链表实现的队列,存放所有的值,便于访问,时间复杂度O(1)。LRUDataStore维护了一个LRUEntity数据表,执行put操作将最新数据封装放入链接头部。

Weak存储层:是以弱引用为原则的数据存储和缓存淘汰机制。实现类为WeakValueDataStore和WeakValueHolder。前者提供数据存储,后者提供基于弱引用的实际值存储逻辑。

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

1、缓存击穿(1)

描述:数据库里有数据,缓存里某一个key不存在,或者key过期失效,通常是热点数据,高并发情况下,造成瞬时DB请求量大、压力骤增,从而崩溃。

解决:

a.互斥锁方案(第一个请求加锁,其他等待,直到第一个拿到数据,其他跟着访问缓存即可,Redis的分布式锁和redisson框架 )。

b.设置热点数据永不过期

2、缓存穿透(0)

描述:缓存里没有数据,数据库里也没有数据。查询一个不存在的数据,因为数据不存在,就不会被写入缓存,所以每次都请求DB,如果流量增大,就会造成缓存穿透。

解决:

a.缓存空值--查询结果返回空值,将其缓存,缓存时间最长不超过五分钟。

b.在缓存之前加一个Bloomfilter布隆过滤器,查询的时候先去Bf确认key是否存在,如果存在再去查询缓存和DB。

3、缓存雪崩(n)

描述:缓存里key对应的数据存在,但多个key过期,即在同一时刻失效,高并发情况下,造成瞬时DB请求量大、压力骤增,从而崩溃。通常由于服务器宕机、多个key设置了相同的过期时间引起。

解决:

a.构建多级缓存框架:Ngnix缓存+redis缓存+其他缓存(如Ehcache)。

b.设置不同的缓存失效时间:在原有的失效时间上增加随机值1-5min,重复率降低,集体失效概率降低。

c.互斥锁:同上,第一个请求加锁,其他等待,直到锁被释放,降低吞吐量,慎用。

(9)Ehcache的注解

开启注解:<cache:annotation-driven cache-manager=”cacheManager”/>

使用标记注解:通过对一个类进行注解修饰的方式在这个中使用缓存注解

@Cacheable:被修饰方法可以缓存、第一次缓存结果、后面t内返回结果即可(不执行代码段)

@CachePut:缓存结果且会执行代码段

@CacheEvict:删除(无效)缓存

Caching:使用同一个缓存注解多次修饰

CachingConfig:类的操作都是缓存操作 时,用来指定类,方便配置

(10)Memcached的内存管理机制

1、Slab内存分配机制:

page 分配给slab的空间,chunk,固定大小的数据区块--记录缓存内容,slab class,chunk组,动态创建的实际内存区。增长因子1.25,chunk大小依次累乘。

提前分配内存slab1MB(默认),再进行小对象填充chunk。Memcached根据数据大小,选择合适的slab,再根据slab内的空闲chunk表,选择合适的chunk,将数据缓存。

避免大量重复的初始化和清理,还有频繁的分配/释放内存,减轻内存负担,减少系统碎片。

但是分配内存长度固定,无法有效利用内存。

利用增长因子调优,控制slab之间的差异,控制chunksize的增长幅度差异,差距越小,利用率越高。

2、Item分配内存机制:

保存在chunk的实际数据,

键长nkey+值长nbytes+后缀长nsuffix+item结构大小,

根据这个快速定位slab classid(1MB,最小冗余slab class),

按照顺序(回收空间slot、slab空间page中、内存剩余memory、LRU)查找,

内存浪费,利用n参数调优,(重新规划slab=chunk*n,slab=chunk,chunk=item,整数倍)

利用增长因子调优,控制slab之间的差异,控制chunksize的增长幅度差异,差距越小,利用率越高。

3、缓存过期策略:

   (1)Lazy Expiration(延迟/惰性 过期)

     Memcached不会监控记录是否过期,而是当客户端来获取数据的时候,才会检查记录的时间戳,CPU不必耗费大量时间监控因此成为Lazy Expiration。

   (2)LRU(Least Recently Used 最近最少使用)

     当空间不足的时候,Memcached会优先使用已经过期的数据空间,如果还不够的话,就会使用LRU算法来分配空间,删除最近最少使用的key/value对,将其空间分配给新的key/value对。如果不希望使用LRU算法时,启动时加-M参数,这样memcached内存耗尽时会返回一个报错信息。要特别注意,Memcached的LRU不是全局的,而是针对slab的,可以说是区域性的。

   (3)惰性删除机制

     删除item对象时,不释放内存,作删除标记,指针放入slot回收插槽,下次分配的时候直接使用。

(11)关系型数据库和非关系型数据库的优缺点分析

关系型数据库:SQLite、MySQL、Oracle ,电信、银行等领域

优点:

1. 容易理解:一个关系型数据库就是由二维表及其之间的联系所组成的数据组织,这种结构贴近逻辑世界,相对网状、层次等模型更容易理解

2. 使用方便:通用的SQL语言使得操作关系型数据库非常方便

3. 易于维护:发展时间长,技术成熟

3. 数据完整性高:具有丰富的完整性(实体完整性、参照完整性和用户定义的完整性),大大降低了数据冗余和数据不一致的概率

4. 数据强一致性:关系型数据库的最大特点就是事务的一致性,严格遵循ACID模型

5. 标准化:支持统一查询语言SQL,可用于复杂的查询

7. 查询效率高:借助索引机制快速查询、高效的查询机制

缺点:

1. 读写性能不佳:为了维护一致性所付出的巨大代价就是其读写性能比较差,尤其是在海量的数据面前

2. 灵活性不高:固定的表结构导致灵活性差

3. 存在I/O瓶颈:对于高并发读写需求,传统关系型数据库的硬盘I/O是一个很大的瓶颈

4. 不支持海量数据:难以有效存储稀疏数据,存储记录数量有限

5. 可扩展性差:纵向扩展花费高,需要购买高额服务器,横向扩展性差

6. 数据库模式相对固定:严格遵循定义和约束,不够灵活

非关系型数据库:MongoDB、Redis、HBase 互联网企业、传统企业的非关键业务(比如数据分析)

优点:

1. 高并发、读写性能好:无需经过SQL层的解析,读写性能高,

2. 扩展性高:基于键值对,数据没有耦合性,容易扩展

3. 数据格式灵活:数据结构化存储方法的集合,非关系型数据库的存储格式是 格式、文档格式、图片格式等等,而关系型数据库只支持基础类型

4.支持海量数据:有效实现稀疏数据的存储管理、高可用。

5. 支持web2.0应用:分布式存储,使用键值对存储数据,与云计算结合紧密

6. 开源:NoSQL项目大都是开源的,允许用户根据自己需求对其进行修改以满足自己需求

缺点:

1. 不提供SQL支持,没有统一查询语言

2. 无事务处理机制

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

4. 缺乏数学理论基础:NoSQL没有统一的理论基础

5. 数据完整性低:不支持ACID模型,而是支持BASE模型,很难实现数据完整性,只能达到数据最终一致性

6. 技术尚不成熟,缺乏专业团队的技术支持,维护较困难等

(12)Redis的数据结构

Redis常用的value包含5种类型:string、list、set、hash、zset。

String:

最基本,

字符串、浮点数、整数,

任何类型数据(二进制、图片、json对象),

编码方式int raw动态字符串 embstr动态字符串

(32字节,SDS-字符数组-len alloc flags buf的 free区域),

基本操作:批量设置键值对、过期和SET 命令扩展、计数

场景:存储图片、统计微博粉丝数

List:

存储String序列,

按照插入顺序排序,可以重复,

可以添加一个元素到列表的头部或者尾部,插入和删除操作非常快,时间复杂度为O(1),但是索引定位很慢,时间复杂度为 O(n)

底层是个链表结构,可以使用ziplist、linkedlist实现

利用迭代器可以从两个方向对链表进行迭代,

压缩列表(ziplist),zbyte字节、ztail偏移量、zlen数量、zlend结束点,prelen、encoding类型长度-根据不同数据改变-redis节省内存、data、复杂度O(1)、O(N)

场景:队列、消息排队异步逻辑处理、文章列表、数据分页展示(有序的)

Quicklist,listpack-压缩列表

Hash:

string类型的field和value的域值映射表,key是哈希表名,ziplist、字典hashtable实现

适合用于存储对象。

链式hash,指向下一个hash,其中hash值相同的键值对链接,减少hash冲突,查询耗时增加,O(n),rehash扩展-两个Hash表-交替使用-迁移-量大阻塞-触发条件负载因子1 or 5和持久化,渐进式rehash-多次迁移-表2插入,查询表1表2,表1只减不增

场景:存储用户信息、分布式生成唯一ID(随机表)

Set:

String 类型的无序无重复集合,无序唯一键值对

内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL

整数集合intset、字典hashtable实现

Intset有序无重复,自动选择读,二分法查找,

场景:标签(文章分类)、去重(共同好友)、随机化展示

Zset:

String 类型的无序无重复集合,每个member关联一个score,

score可以重复,按照score排序,

Ziplist、skiplist跳表实现

skiplist跳表:范围查询-常数复杂度获取权重、哈希表实现,多层的有序链表,快读定位数据,O(logN)

场景:排行榜,IM最近会话列表

(13)Redis的持久化方式

区别:备份模式、间隔时间、数据格式、是否阻塞

全量模式:

描述:RDB(快照模式),dump.rdb ,Redis将内存中的所有数据全量写入到文件中,save 900 1, save RDB,不会fork,阻塞。bgsave #会fork一个新进程,系统自动触发也是使用的bgsave,非阻塞式。

优点:每隔一段时间进行所有数据的备份,灾备简单、远程传输,只需要fork一个子进程,不影响主进程。

缺点:故障丢失最后一次所有数据备份,数据备份时,导致内存膨胀两倍,多了负载内存CPU卡顿。突然中断无法保证数据强一致。

场景:适合于大规模的数据恢复,并且还原速度快,如果对数据的完整性不是特别敏感(可能存在最后一次丢失的情况)

增量模式:

描述:AOF(追加/日志模式),默认存储文件为appendonly.aof,存储 Redis 服务器已经执行过的的命令,并且只记录对内存有过修改的命令。以日志的形式来记录用户的请求写操作,以追加的形式进行记录到aof文件中,

写入机制:内容放到内存缓冲区,填满才落盘。越早地把命令写入到磁盘中,发生意外时丢失的数据就会越少。

优化:重写机制-长期运行-合并历史记录,aof文件会越变越长,BGREWRITEAOF,新的 aof 文件,体积会小,不会被阻塞。

自动触发AOF重写:当前文件的容量是之前的两倍,当前文件大于64mb。

(14)Redis集群的演进

主从集群:

主-可读写,从-可读。

主从同步/复制:SYNC--BGSave-发送快照-复制加载-缓存命令同步

优点:解决单机并发量大问题,分担主节点的读压力,读写分离,可用性和性能,哨兵的基础,异步方式-同步,仍然可以响应客户端。

缺点:数据不一致性,不能自动容错和恢复,主从切换-人为操作费用高。

哨兵集群:

主从复制+主节点故障转移

特点:哨兵)统一配置管理(主从地址、监控正常、通知问题、故障迁移-主从切换

核心:Raft算法

适合:分布式系统,系统容错,以及Leader选举

原理:哨兵定期向主从+其他哨兵发送ping命令,如果主服务器有效回复超时,标记为主观下线,所有哨兵以每秒一次的频率持续向主服务器确认,多数同意才能标记为客观下线,此时Info命令频率改变。如果数量不够就不能标记客观下线,直到返回有效回复,移出主观下线状态。

优点:

主从模式的升级,提高了系统的可用性和性能、稳定性

自动进行故障恢复

哨兵与哨兵之间、哨兵与master之间能够进行及时的监控,心跳检测

缺点:

一主多从的模式会遇到写的瓶颈,故障恢复的时间长,写的业务就会受到影响

增加了系统的复杂度,需要同时维护哨兵模式

Redis集群

描述:redis数据分布式存储、分片、不同节点不同内容、收缩-故障恢复、扩容

目的:读写性能受限、扩容、单机存储

特点:至少3主3从,不同的配置文件

主节点-读写-slot集合,从节点-备份、故障转移、读写分离。

每个节点负责部分hash槽,每个槽存放数据。

ClusterNode-元数据信息。

节点通信:meet/ping、pong

优点:去中心架构,故障转移-主从切换,可以实现读写分离,高速查询效率(哈希槽),不同节点存储不同内容--分片--避免单机缓存问题,扩容收缩--横向纵向扩展能力

缺点:数据一致性,冷备,架构复杂

(15)综合系统设计

1、set的使用:抽奖系统(数据结构、负载均衡、网关限流、分布式缓存等)

a.基本命令操作:

SADD增加元素

SREM 删除元素

SISMEMBER,查询某个 value 是否存在,相当于 contains

SRANDMEMBER,随机获取元素

SINTER/SUNION/SDIFF:交并差集

SCARD,获取长度/总个数

SINTER/SUNION/SDIFF+STORE:存储到某个key

b.需要考虑的情况:

静态资源放到cdn:抽奖活动的页面中,大部分内容都是静态的,只有抽奖按钮需要与服务端交互;对此可以通过客户端、CDN缓存等提升用户体验。

防用户误操作:客户端请求的时候判断时间是否在活动范围内,

防刷:营销活动是拿真金白银来推广,所以需要有效的机制能防止被人恶意攻击,将全部奖品刷走。防恶意注册用户、防恶意调用接口、防奖品被少部分人获取

高并发:当抽奖并发量大时,写DB的压力会很大。前端发送请求队列化处理,避免用户不停点击,造成大量请求,高并发的核心思路是逐级分流,通过缓存、队列、消息等手段将大流量逐步分散。缓存:不常变动、实时性要求不高、频繁变动不持久化、合适数据结构、缓存失效算法。以空间换时间,通过缓存来提升每个请求的处理速度,提升系统并发量。异步处理,分析并识别出可以异步处理的逻辑,将他们异步化。分层逐级拦截非法请求,仅让有效的请求到达底层系统;尽可能让每一次写操作都能成功。根据每个系统的服务能力,设定流量极限,流量超过极限值后进行限流。

具体采取哪种策略看具体的需求, 对数据的准确性实时性需求、性能需求等. 可以同时结合多种策略. 以及时间间隔也取决于产品需求和刷新耗时.

高可用:多实例部署;营销系统内部无状态,并可以通过水平扩展,提升系统性能。隔离技术的核心是防止压力、异常等相互传导,导致服务不稳定甚至不可用。限流技术,业务上主要通过计数器的方式进行防刷性限流

防止奖品超发:乐观锁、悲观锁、分布式锁。同步队列。缓存+异步。具体采取哪种策略看具体的需求, 对数据的准确性实时性需求、性能需求等. 可以同时结合多种策略. 以及时间间隔也取决于产品需求和刷新耗时.

电商秒杀:(类似)

超卖(分布式锁),请求-秒杀-访问/查询库存-下单-扣除/更新库存,消息队列限流

2、zset 的使用:排行榜 ,IM最近会话列表

a.基本命令操作:

ZSCORE,获取指定 value 的 score

ZRANK,确定某个值的排名

ZRANGEBYSCORE,根据分值区间遍历zset,分值区间内排名

ZREM,删除value

ZINCRBY key increment member,自增,数据和排行问题,描述:有序集合中对指定成员的分数加上增量 increment,比如你要给某个直播间做排行榜,key就是直播间相关的key,member就是邀请人的标识(一般就是userId),incrementScore就是这个人邀请的人数自增量,比如微博热搜排序,key就可以是小时榜/天榜/月榜,member是某一条热搜词条,incrementScore就是这个词条热度增量/权重增量),

ZREVRANGEBYSCORE key max min [WITHSCORES],根据分值区间遍历 zset,分值区间内排名。

b.需要考虑的情况:

为什么使用Zset:首先排行榜明显是一个热点数据, 访问频率大, 且计算复杂. 肯定不能直接从数据库中读取计算排名, 否则服务很容易挂掉。所以只能用缓存,而zset 是一个有序列表, 满足排序需求,redis 数据存在内存中, 存取效率高。其中zset 使用ziplist 或 skiplist+map实现. 直接查询用户积分时间复杂度低。

基本结构:对于整个排行榜, 我们用 zset 保存排行榜数据, key 为排行榜信息, member 为用户id, score 存储用户积分。用户信息(排行榜需要的头像昵称) 再用string或hash结构存储。

相同积分下的排序--score 设计:zset对于score相同的排序是按照key的map字典序排的,所以我们考虑在score里面加入时间信息,比如score = 积分 * 1E10 + 最大时间 - 当前时间,注意生成的score最大值不能越界.如果排行榜是临时的,超过某个时间就不存在或不保证数据的准确性, 那最大时间直接取排行榜的截止有效时间就可,这种方式时间信息占用的位数较少。如果排行榜一直存在就取固定值, 根据实际业务使用固定最大时间,满足实际业务场景。

缓存的定时刷新保证数据准确性:虽然我们将排行榜数据存入zset中, 但这个只是提高了我们的访问效率, 并不能完全保证数据的准确性和最终一致性. 可能会因为各种原因(高并发, 网络异常)导致缓存数据不准确, 因此需要定时刷新缓存数据.

缓存刷新策略:

全量刷新: 把所有缓存数据都重新计算一遍, 比如每天(一定时间内)刷一遍

增量刷新: 把一定时间内变化的缓存数据刷新, 每个小时刷一次

根据数据变化频率动态刷新: 类似redis持久化策略. 一定时间内变化的频率到达一个阈值就刷新.

具体采取哪种策略看具体的需求, 对数据的准确性实时性需求、性能需求等. 可以同时结合多种策略. 以及时间间隔也取决于产品需求和刷新耗时.

预防缓存击穿的必要性:如果缓存过期后用户访问排行榜, 这个时候就需要从数据库中查询相关数据, 重新计算排行榜前n位, 假如这个时候是大量用户并发访问, 然后查询排行榜缓存, 发现没有数据, 于是都去查询数据库重算. 这个时候数据库压力就会很大, 很容易挂掉. 即缓存击穿.

预防缓存击穿的解决方式:

a.不设置过期时间, 不过期就不会失效.

b.加锁, 重新加载缓存的时候加锁, 防止所有的请求都去数据库查询重算.

然后结合具体场景使用,具体采取哪种策略看具体的需求。

以上是关于大数据存储技术期末复习(自用)的主要内容,如果未能解决你的问题,请参考以下文章

数据科学与大数据技术专业 —— 云计算●虚拟化 课程 期末复习卷及其简答

大数据技术原理与应用 第三版 林子雨 期末复习大数据概述 第一章 P2

大数据与云计算期末复习

大数据开发技术期末复习(不挂科)

数据科学与大数据技术专业 —— 云计算●虚拟化 课程 期末复习卷及其简答

数据科学与大数据技术专业 —— 云计算●虚拟化 课程 期末复习卷及其简答