一、缓存Cache
1.1 缓存的概念
缓存是存储计算机原始数据的复制集,以便于访问。
1.2 缓存击穿
概念:
对于一些设置了过期时间的的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据
原因:
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,该key没有命中,大量请求穿透到数据库服务器
解决方案:
对于热点数据,慎重考虑过期时间,确保热点期间key不会过期,甚至有些可以设置永不过期
使用互斥锁(比如Java的多线程锁机制),第一个线程访问key的时候就锁住,等查询数据库返回后,把值插入到缓存后再释放锁
1.3 缓存雪崩
概念:
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力剧增,引起雪崩。
原因:大量缓存在同一时间失效;大量请求落到后端DB上;
解决方案:
不同的key可以设置不同的的过期时间(随机值),让缓存失效的时间点尽量均匀;
做二级缓存,A1为初始缓存,A2为拷贝缓存,A1失效时可以访问A2
1.4 缓存穿透
概念:
访问一个一定不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉
原因:
key被高并发访问;该key没有命中,去后端DB获取;大量请求穿透到数据库服务器
解决方案:
布隆过滤器
使用一个足够大的的bitmap,用于存储可能访问的key,不存在的key直接被过滤,避免对底层数据存储系统造成压力
访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间
二、Redis简介
2.1 Redis是一个开源的,内存中的数据结构存储系统,它可以作为数据库、缓存和消息中间件。它支持多种数据结构如字符串(String)、散列(hashes)、列表(lists)、集合(set)、有序集合(sorted set)与范围查询,bitmaps,hyperlogs和地理空间(geospatial) 索引半径查询。 Redis 内置了复制(replication),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions)和不同级别的 磁盘持久化(persistence),并通过哨兵(Sentinel)和自动分区(Cluster)提供高可用性。
2.2 关系型数据库和非关系型数据库之间的区别
关系型:存储于硬盘中,速度慢,只支持基础类型,有多表查询机制,扩展较难,适用于持久存储,海量存储,事务能力强,强调数据的强一致性
非关系型:数据存于缓存中,速度快,k-v文档,图片等,数据之间没有耦合,容易扩展,不是持久存储,海量存储,事务能力弱,强调数据的最终一致性
2.3 Redis常用的数据结构
String:以文本、JSON形式存储的情况比较多
Hash:比较适合存储二维表行列
list:消息队列,头尾都可以获取添加
set:集合、取交集并集(关注,取消关注)
sortedset:排行榜
三、Redis的事务机制
3.1 Redis事务是一个单独的隔离 *** 作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队
Multi、Exec、discard
输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行
输入入Exec后,Redis会将之前的命令队列中的命令依次执行
组队的过程中可以通过discard来放弃组队
3.2 事务的错误处理
组队阶段某个命令出现了报告错误,执行时整个的所有队列会都会被取消。
执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚
3.3 事务锁的机制
悲观锁
乐观锁
四、数据的持久化
4.1 RDB(Redis DataBase)
RDB持久化可以在指定时间间隔内生成数据集的时间点快照,这是默认的持久化方式。
这种方式是将内存中的数据以快照的方式存入二进制文件中,默认的文件名为dump.rdb
RDB提供了三中出发机制save,bgsave,自动化
save触发方式
该命令会阻塞当前Redis服务器,执行行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
bgsave触发模式
执行该命令时,Redis会在后台异步进行快照 *** 作,快照同时还可以响应客户端请求。
Redis进程执行fork *** 作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。
阻塞只发生在fork阶段,一般时间很短。
自动触发模式
自动触发是由我们的配置文件来完成的
RDB的优势
RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何 *** 作
RDB在恢复大数据集时的速度比AOF要快
劣势:
当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程内存数据
父进程修改内存子进程不会反应出来
所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
4.2 AOF
全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,Redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
rewrite策略
重写日志,减少日志文件的大小,redis提供了bgrewriteaof命令。
将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。
将整个内存中的数据库内容用命令的方式重写了一个新的aof文件
AOF触发策略
总是同步always
同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
每秒同步everysec
异步 *** 作,每秒记录 如果一秒内宕机,有数据丢失
不同步no
从不同步
AOF的优势
AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync,最多丢失一秒的数据
AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
AOF日志文件即使过大的时候,出现后台重写 *** 作,也不会影响客户端的读写。
AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复
劣势:
对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
4.3 RDB和AOF的选择
如果同时使用AOF和RDB,那么启动时以AOF为恢复数据的模板
俩者加一起才是最好
五、数据同步机制(主从复制)
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。
全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份
从服务器连接主服务器,发送SYNC命令
主服务器接收到SYNC命令后,开始执行BGSALVE命令生成RDB文件,并且在发送期间继续记录被执行的写命令。
主服务器BGSAVE执行完之后,想所有从服务器发送快照,并且在发送期间激素记录被执行的写命令。
从服务器接收到主服务器的快照后,开始载入快照
主服务器在发送完快照之后开始向从服务器发送缓冲区中的写命令
从服务器完成对快照的载入后,开始执行主服务器发送来的缓冲区的写命令
增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写 *** 作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务接收并执行收到的写命令。
主从复制的异步性
主从复制对于主Redis服务器来说是非阻塞的着当从服务器在进行主从复制同步过程中,主redis仍然可以处理外界的访问请求
主从复制对于从redis服务器来说也是非阻塞的
这意味着即使从redis在进行主从复制过程中也可以接受外界的查询请求,只不过这时候从redis返回来的是老数据。
六、Redis哨兵
6.1 哨兵的功能于作用
监控
Sentienl会不断的检查你的主服务器和从服务器是否正常运行
提醒
当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程程发送通知
自动故障转移
当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移 *** 作, 它会将失效主服器中的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。
6.2 哨兵的工作原理
在redis sentinel中,一共有3个定时任务,通过这些任务,来发现新增节点和节点的状态。
每10秒每个sentinel节点对master节点和slave节点执行info *** 作
每2秒每个sentinel节点通过master节点的channel(sentinel:hello)交换信息
每1秒每个sentintel节点对master节点和slave节点以及其余的sentinel节点执行ping *** 作
主观下线(SDOWN):当前sentintel节点认为某个redis节点不可用。
如果一个实例(instance)距离最后一次有效回复PING命令的时间超过down-after-milliseconds所指定的值,那么这个实例会被Sentinel标记为主观下线。
如果一个主服务器被标记为主观下线,那么正在监视这个主服务器的所有Sentinel节点,要以每秒一次的频率确认主服务器的确进入了主观下线状态。
客观下线(ODOWN)一定数量sentinel节点认为某个redis节点不可用。
如果一个主服务器被标记为主观下线,并且有足够数量的Sentinel(至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断,那么这个主服务器被标记为客观下线。
在一般情况下,每个Sentinel会以每10秒一次的频率,向它已知的所有主服务器和从服务器发送INFO命令。当一个主服务器被Sentinel标记为客观下线时,Sentinel向下线主服务器的所有从服务器发送INFO命令的频率,会从10秒一次改为每秒一次。
Sentienl和其他Sentinel协商主节点的状态,如果主节点处于SDOWN状态,则投票自动选出新的主节点。将剩余的从节点指向新的主节点进行数据复制。
当没有足够数量的Sentinel同意主服务器下线时,主服务器的客观下线状态就会被移除。
当主服务器重新向Sentinel的PING命令返回有效回复时,主服务器的主观下线状态就会被移除。
七、Redis的高可用
7.1 在Redis中,实现高可用技术主要包括持久化、哨兵、复制、集群
持久化:将数据保存在硬盘,保证数据因程序退出而丢失
复制:复制是Redis高可用的基础,哨兵和集群都是在复制的基础上实现的
哨兵:在复制的基础上,哨兵实现了自动化故障恢复,缺陷是写 *** 作无法负载均衡,存储能力受到单机的限制
集群:通过集群,Redis解决了写 *** 作无法负载均衡以及存储能力受到单机限制的问题。
7.2 集群设计思想
不同节点分别管理不同的key
同一个key只让一个master处理
为了保证master的(单点故障)问题,每个主节点至少准备一个slave节点
集群是一个可以在多个Redis节点之间进行数据共享的设施
集群不支持那些需要同时处理多个键的Redis命令
八、一致性Hash
8.1 算法原理
取模:对2的23次方取模
整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推
整个由2^32个点组成的圆环称为Hash环
服务器:将各个服务器使用Hash进行一个哈希,这样每台机器就能确定其在哈希环上的位置
数据:数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置
定位:沿环顺时针“行走”,第一台遇到的服务器就是数据应该定位到的服务器
8.2 算法容错性
当我们进行添加新的服务器或者删除服务器的时候它只影响它的下一个节点
8.3 数据倾斜与虚拟节点
均匀一致性hash的目标是如果服务器有N台,客户端的hash值有M个
那么每个服务器应该处理大概M/N个用户,也就是每台服务器负载尽量均衡
九、Redis的Slot槽
Redis集群使用数据分片而非一致性Hash来实现
一个Redis集群包含由16384个哈希槽,数据库中的每个键都属于这16384个槽中的一个,集群使用公式CRC16(key)%16384来计算当前key属于哪个槽
将一个哈希槽从一个节点移动到另一个节点不会造成节点的阻
每个node被平均分配一个solt段,对应0-16383,slot不能重复也不能缺失,否则会导致数据重复存储或无法存储
node之间也相互监听,一旦有node退出或加入,会按照slot为单位进行数据的迁移
node1如果掉线了,0-5640这些solt会被均分到node2和node3上
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)