Redis必知必会系列
1.常用命令
2.Redis是什么
3.数据类型
- String 是 Redis 最基本的类型,可以理解成与 Memcached一模一样的类型,一个 Key 对应一个 Value,键值分别最大能存储 512M。String类型二进制安全的,意思是Redis的String包含任何数据,比如图片或者序列化的对象。
- Hash是一个键值(key-value)的集合。Redis 的 Hash 是一个 String 的 Key 和 Value 的映射表,Hash 特别适合存储对象。
- List 列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。List 就是链表(双向链接),可以用来当消息队列。
- Set 是 String 类型的无序集合。集合是通过 hashtable 实现的。Set 中的元素是没有顺序的,而且是没有重复的。
- Zset(Sorted Set)和 Set 一样是 String 类型元素的集合,且不允许重复的元素。当你需要一个有序的并且不重复的集合列表,那么可以选择 Sorted Set 结构。和 Set 相比,Sorted Set关联了一个 Double 类型权重的参数 Score,使得集合中的元素能够按照 Score 进行有序排列,Redis 正是通过分数来为集合中的成员进行从小到大的排序。实现方式:Redis Sorted Set 的内部使用 HashMap 和跳跃表(skipList)来保证数据的存储和有序,HashMap 里放的是成员到 Score 的映射。而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 Score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
4.缓存中间件,Memcache和Redis的区别
- Memcache:代码层次类似Hash,非常简单易用;支持简单的数据类型,但是不支持数据的持久化存储,如果服务器宕机了,数据是无法保存的;不支持主从同步;不支持分片机制,Value 的大小只有 1MB
- Redis:数据类型丰富;支持数据磁盘持久化存储;支持主从;支持分片,Value 的大小可以达到 1GB
5.Redis为什么可以这么快
- 完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高(Redis是采用单进程单线程模型的K-V数据库,由c语言编写,将数据存储到内存中,读写数据的时候都不会受到硬盘IO速度的限制)
- 数据结构简单,对数据操作也简单(Redis不使用表,它的数据库不会预定义或者强制要求用户对redis存储的不同数据进行关联,因此性能相比关系型数据库要高出不止一个量级,其存储结构就是键值对,类似于hashMap,hashMap的优势就是查询,查询的时间复杂度是O(1))
- 采用单线程,单线程也能处理高并发请求,想多核也可启动多实例(在面对高并发的请求的时候,首先想要的是多线程来进行处理,将IO线程和业务线程分开,业务线程使用线程池来避免频繁创建线程和销毁线程,即便是一次请求,阻塞了也不会影响到其它请求。Redis单线程结构是指主线程是单线程的,主线程包含IO事件的处理,以及IO对应的相关请求的业务处理,此外,主线程还负责过期键的处理,复制协调,集群协调等等,这些除了IO事件之外的逻辑会被封装成周期性的任务,由主线程周期性的处理,正因为采用单线程的设计,对于客户端的所有读写请求,都由一个主线程串行的处理,因此多个客户端同时对一个键进行写操作的时候,就不会有并发的问题,避免了频繁的上下文切换和锁竞争,使得redis执行起来效率更高。单线程是可以处理高并发的请求的,并发并不是并行,并行性意外着服务器能够同时执行几个事情,具有多个计算的单元,而并发性IO流,意味着能够让一个计算单元来处理来自多个客户端的流请求。Redis使用单线程配合上IO多路复用,将可以大幅度的提升性能,在多核CPU流行的今天,只要一个线程,只用一个核很浪费,CPU不是制约redis的性能瓶颈,瓶颈可能是机器内存的大小或者网络带宽。此外,可以在多核的服务器中启动多个实例来利用多核的特性。注意,这里的单线程只是在处理我们的网络请求的时候,只有一个单线程来处理,一个正式的Redis server,在运行的时候,肯定不止一个线程的,例如Redis在进行持久化的时候,会根据实际情况,以子进程子线程的方式执行)
- 使用多路I/O复用模型,非阻塞IO(Redis是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或者输出都是阻塞的,所以IO操作在一般情况下,往往不能直接返回,就会导致某一文件的IO阻塞,进而导致整个进程无法对其它客户端提供服务。而IO多路复用就是为了解决这个问题而出现的)
6.FD
7.传统的阻塞I/O模型
8.多路I/O复用模型
- 因地制宜的,Redis需要在多个平台下运行,为了最大化的提高执行效率和性能,会根据编译平台的不同选择不同的IO多路复用函数作为子模块,提高给上层统一的接口
- 优先选择时间复杂度为O(1)的IO多路复用函数作为底层实现
- 一般以时间复杂度为O(n)的select作为保底(如果编译环境没有epoll、kqueue、evport、就会使用select作为备选方案,使用时会扫描全部的文件描述符,性能较差,时间复杂度是O(n))
- 基于react设计模式监听I/O事件(Redis采用react设计模式来实现文件处理器的,文件事件处理器使用IO多路复用模块,同时监听多个FD,当accept、read,write等事件产生的时候,事件处理器就会回调FD绑定的事件处理器,虽然整个事件处理器是在单线程运行的,但是通过IO多路复用模块的引用,实现了同时对多个FD读写的监控,提高了网络通信模型的性能,同时来保证了整个Redis服务实现的简单)
9.Redis内部内存管理
- type :代表一个 value 对象具体是何种数据类型。
- encoding :是不同数据类型在 redis 内部的存储方式,比如:type=string 代表 value 存储的是一个普通字符串,那么对应的 encoding 可以是 raw 或者是 int,如果是 int 则代表实际 redis 内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123"这样的字符串。
- vm 字段:只有打开了 Redis 的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。 Redis 使用 redisObject 来表示所有的 key/value 数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给 Redis 不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用。
10.缓存穿透
- 业务自身代码或数据出现问题
- 一些恶意攻击、爬虫造成大量空的命中
- 设置布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,拦截不存在的数据
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)
11.缓存击穿
- 设置热点数据永远不过期
- 加互斥锁
12.缓存雪崩
- 设置redis集群和DB集群的高可用,如果redis出现宕机情况,可以立即由别的机器顶替上来。这样可以防止一部分的风险
- 使用互斥锁,在缓存失效后,通过加锁或者队列来控制读和写数据库的线程数量。比如:对某个key只允许一个线程查询数据和写缓存,其他线程等待。单机的话,可以使用synchronized或者lock来解决,如果是分布式环境,可以是用redis的setnx命令来解决
- 不同的key,可以设置不同的过期时间,让缓存失效的时间点不一致,尽量达到平均分布
- 永远不过期,redis中设置永久不过期,这样就保证了,不会出现热点问题,也就是物理上不过期
- 可以利用ehcache等本地缓存来暂时支持,但主要还是要对源服务访问采取限流、资源隔离(熔断),降级措施等
13.如何从海量Key里面查询出某一固定前缀的Key
(一)使用keys pattern,查找所有符合给定模式pattern的key,keys一次性返回所有匹配的key,键的数量过大会使服务卡顿。
(二)使用非阻塞scan指令,但获取的数据是随机的,可能会获取到重复key,无法统计。
14.分布式锁需要解决的问题
- 互斥性(任意时刻只能有一个客户端获取锁,不能同时有两个客户端获取到锁)
- 安全性(锁只能被持有该锁的客户端删除,不能由其它客户端删除掉)
- 死锁(获取锁的客户端因为某些原因而宕机,而未能释放锁,其它客户端再也无法获取到该锁,而导致的死锁,此时需要有机制避免这种问题的发生)
- 容错(部分redis节点宕机,客户端要保证可以获取锁和释放锁)
15.Redis实现分布式锁
SETNX key value,如果key不存在,则创建并赋值。SETNX即set if not exist,时间复杂度是O(1),返回值:设置成功,返回1;设置失败,返回0。
正因为SETNX的操作是原子性的,因此初期便被用在实现分布式锁,在执行某段代码逻辑的时候,先尝试使用SETNX对某个key设值,如果设值成功,则证明此时没有别的线程在执行该段代码,或者说占用该独占资源,这个时候线程就可以顺利的去执行该段代码逻辑了,如果设值失败,则证明此时有别的程序或者线程占用该资源,那么当前线程就需要等待直至设值SETNX成功,如果设值SETNX的key,这个key就会长久有效了,后续线程如何能再次获得到锁,此时需要给该key设值一个过期时间。
(一)使用EXPIRE key seconds设值过期时间:
- 设值key的生存时间,当key过期的时候(生存时间为0),会被自动删除
- 缺点:原子性得不到满足(如果SETNX与EXPIRE结合使用,它们分别都是原子性的,但是组合到一起却不是原子性的)
(二)完美方案
- EX seconds,设值键的过期时间为second秒。
- PX milliseconds,设值键的过期时间为millisecond毫秒。
- NX,只在键不存在的时候,才对键进行设值操作。效果等同于SETNX。
- XX,只在键已经存在的时候,才对键进行设置操作。
16.大量的key同时过期的注意事项,如何避免系统卡断现象
17.实现异步队列
- 使用List作为队列,rpush生产消息,lpop消费消息,实现先进先出的效果,缺点:没有等待队列里有值就直接消费,可以在应用层引入sleep机制去调用lpop重试来弥补
- BLPOP key [key...] timeout:阻塞直到队列有消息或者超时。BLPOP可以替代sleep做更精准的阻塞控制,缺点:只能供一个消费者消费
- pub/sub,主题订阅者模式,发送者(pub)发送消息,订阅者(sub)接收消息,订阅者可以订阅任意数量的频道,可以实现一对多的消费队列,缺点:消息的发布是无状态的,无法保证消息是否送达达,解决这个问题,可以使用专业的消息队列:kafka等
18.Redis持久化
(一)RDB(快照)持久化:保存某个时间点的全量数据快照,为一个二进制文件
(1)缺点:
- 内存数据的全量同步,数据量大会由于I/O而严重影响性能的。每次快照持久化都是将快照数据完整的写入到磁盘一次,并不是增量的只同步脏数据,如果数据量大的话,并且写操作比较多的时候b必然会引起大量的磁盘IO操作,可能会严重性能。
- 可能会因为Redis挂掉而丢失从当前至最近一次快照期间的数据,由于快照方式是在一定间隔时间做一次的快照后的所有修改,如果应用要求不能丢失任何修改的话,可以采用AOF。
(2)Redis参数设置说明:
(3)命令生成RDB文件
(4)自动化触发RDB持久化的方式
(5)BGSAVE原理
(二)AOF(append-only-file)持久化,通过保存Redis服务器所执行的写状态来记录数据库的。
(1)记录下除了查询以外的所有变更数据库状态的指令(以redis协议格式来保存的)
(2)以append的形式追加保存到AOF文件中,以增量的形式(数据库会记录下所有变更数据库状态的指令,除了指定数据库的查询命令,其它的命令都是来自client)
(3)refis.conf配置说明
- always表示一旦缓存区的内容发生变化,就总是及时的将缓存区的内容写入到aof中
- everysec是将缓存区的内容每隔一秒去写入到aof中
- no是将写入aof的操作交由操作系统来决定
- 一般而言,为了提高效率,操作系统会将缓存区被填满才会开始同步数据到磁盘中。一般推荐everysec默认的方式,速度比较快,安全性比较高
(4)日志重写解决AOF文件大小不断增大的问题原理
- 首先调用fork(),创建一个子进程
- 子进程把新的AOF写到一个临时文件里面,不依赖原来的AOF文件(新的AOF的重写是直接把当前内存的数据生成对应的命令,并不需要读取老的AOF文件进行分析或者合并)
- 主进程持续将新的变动同时写到内存和原来的AOF里(这样即使写入失败,也能保证数据的安全)
- 主进程获取子进程重写AOF的完成信号,往新AOF同步增量变动
- 使用新的AOF文件替换掉旧的AOF文件。
(三)AOF和RDB的混合模式
- BGSAVE做镜像全量持久化,AOF做增量持久化,因为BGSAVE会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据的问题,需要AOF配合使用,在Redis重启的时候会使用BGSAVE持久化文件,重新构建内容,再使用AOF重放近期的操作指令,来实现完整恢复之前的状态
- AOF重写机制,它其实也是先写一份全量数据到AOF文件中,再追加增量,只不过全量数据是以redis命令格式写入的,那么是否可以先以RDB格式写入全量数据,再追加增量数据呢,这样既可以提高重新和恢复速度,也可以减少文件的大小,还同时可以保证数据的完整性,能够结合RDB和AOF的优点,AOF和RDB的混合模式正是在这种需求下诞生的。在此种方式下,子进程在做AOF重写的时候,会通过管道从父进程读取增量数据并缓存下来,那么在以RDB格式保存全量数据的时候,也会从管道读取数据,同时不会造成管道的阻塞,也就是说,AOF文件前半段是RDB格式的全量数据,而后半段是Redis命令格式的增量数据。
19.RDB和AOF文件共存情况下的恢复流程
20.RDB和AOF的优缺点
- RDB优点,RDB本质上是一个内存快照,保存了创建RDB文件那个时间点的Redis全量数据,全量数据快照,文件小,创建恢复快
- RDB缺点,无法保存最近一次快照之后的数据
- AOF优点,AOF本质上是一份执行日志,保存所有被Redis更改的指令,可读性高,适合保存增量数据,数据不易丢失
- AOF缺点,文件体积大,恢复时间长
21.Pipeline的好处
22.主从同步原理
(一)全同步过程
- Slave发送sync命令到Master。
- Master启动一个后台进程,将Redis中的数据快照保存到文件中(BGSAVE)
- Master将保存数据快照期间接收到的写命令缓存起来
- Master完成写文件操作后,将该文件发送给Slave
- 使用新的AOF文件替换掉旧的AOF文件(Slave将接收到的文件保存到磁盘中,加载文件到内存中去恢复数据快照)
- Slave完成数据快照恢复后,Master将这期间收集的增量写命令发送给Slave端,进行回放
(二)增量同步过程
- Master接收到用户的操作指令,执行相应的操作函数,判断是否需要传播到Slave
- 将操作记录追加到AOF文件,首先将操作转换成Redis内部的协议格式,并以字符串的形式存储,并追加到AOF文件
- 将操作传播到其它Slave,主要有两步处理,首先对齐主从库(确保是该操作的从数据库),然后,往响应缓存写入指令
- 将缓存中的数据发送给Slave
23.Redis Sentinel工作原理
- 监控:检查主从服务器是否运行正常
- 提醒:可以通过API向管理员或者其它应用程序发送故障通知
- 自动故障迁移:主从切换(在Master宕机后,将其中一个Slave升级为Master,将其他的Slave从该节点同步数据)
主从切换过程:PING命令时间超时》master被 Sentinel 标记为主观下线》足够数量的 Sentinel同意后,master标记为客观下线》Sentinel投票选出新master,将剩余slave指向新的master进行数据复制
24.流言协议Gossip(在杂乱无章中寻求一致)
- 每个节点都随机的与对方通信,最终所有节点的状态达成一致
- 种子节点定期随机向其他节点发送节点列表以及需要传播的消息
- 不保证信息一定会传递给所有节点,但是最终会趋于一致
25.Redis集群原理
(一)如何从海量数据里快速找到所需
(二)原理
(三)目的
(四)一致性哈希算法
26.Redis怎么用
27.缓存和数据库数据一致性问题
- 先删除缓存
- 再写数据库
- 休眠指定毫秒
- 再次删除缓存
- 实现了异步更新缓存,降低了系统的耦合性
- 但是破坏了数据变化的时序性
- 成本相对比较高
- 在mysql压力不大情况下,延迟较低
- 和业务完全解耦
- 解决了时序性问题
- 成本相对而言比较大
28.淘汰策略
- volatile-lru(Least Recently Used):从已设置过期时间的数据集中优先对最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集中优先剩余时间短的数据淘汰
- volatile-random:从已设置过期时间的数据集中随机选择数据淘汰
- allkeys-lru:从所有数据集中优先对最近最少使用的数据淘汰
- allkeys-random:从数据集随机选择数据淘汰
- no-enviction:不淘汰策略,若超过最大内存,返回错误信息
Redis必知必会系列的更多相关文章
- mysql必知必会系列(一)
mysql必知必会系列是本人在读<mysql必知必会>中的笔记,方便自己以后查看. MySQL. Oracle以及Microsoft SQL Server等数据库是基于客户机-服务器的数据 ...
- H5系列之History(必知必会)
H5系列之History(必知必会) 目录 概念 兼容性 属性 方法 H5方法 概念 理解History Api的使用方式 目的是为了解决哪些问题 作用:ajax获取数据时 ...
- H5系列之地理位置(必知必会)
H5之地理位置必知必会 [02]概念 规范地址:http://www.w3.org/TR/geolocation-API/ HTML5 Geolocation(地理定位)用于定位用 ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- SQL 必知必会
本文介绍基本的 SQL 语句,包括查询.过滤.排序.分组.联结.视图.插入数据.创建操纵表等.入门系列,不足颇多,望诸君指点. 注意本文某些例子只能在特定的DBMS中实现(有的已标明,有的未标明),不 ...
- 《MySQL必知必会》[01] 基本查询
<MySQL必知必会>(点击查看详情) 1.写在前面的话 这本书是一本MySQL的经典入门书籍,小小的一本,也受到众多网友推荐.之前自己学习的时候是啃的清华大学出版社的计算机系列教材< ...
- Android程序员必知必会的网络通信传输层协议——UDP和TCP
1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...
- 《MySQL必知必会》整理
目录 第1章 了解数据库 1.1 数据库基础 1.1.1 什么是数据库 1.1.2 表 1.1.3 列和数据类型 1.1.4 行 1.1.5 主键 1.2 什么是SQL 第2章 MySQL简介 2.1 ...
- 脑残式网络编程入门(三):HTTP协议必知必会的一些知识
本文原作者:“竹千代”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.前言 无论是即时通讯应用还是传统的信息系统,Http协议都是我们最常打交 ...
- 《MySQL必知必会》学习笔记——前言
前言 MySQL已经成为世界上最受欢迎的数据库管理系统之一.无论是用在小型开发项目上,还是用来构建那些声名显赫的网站,MySQL都证明了自己是个稳定.可靠.快速.可信的系统,足以胜任任何数据存储业务的 ...
随机推荐
- JDBC(一)—— JDBC概述
Jdbc概述 Java DataBase connectivity(Java语言连接数据库) Jdbc本质是什么? 是Sun公司制定的一套接口,java.sql.* 接口都有调用者和实现者 面向接口调 ...
- 【题解】Fuzzy Google Suggest(UVA1462)
题目链接 题意 给定一个字符串集合,有n次搜索,每次有一个整数x和一个字符串,表示可以对字符串进行x次修改, 包括增加.修改和删除一个字符,问修改后的字符串可能是字符集中多少个字符串的前缀. 思路 简 ...
- IDEA注册码(附修改hosts文件的方法)
推荐获取IDEA注册码的网站:http://idea.lanyus.com/ 亲测好用! 也可复制下边的注册码: K71U8DBPNE-eyJsaWNlbnNlSWQiOiJLNzFVOERCUE5F ...
- 11g RAC开启归档模式
1.关闭集群数据库 [oracle@rac01-+ASM1 ~]$ srvctl stop database -d rac 2.开启节点一数据库到mount状态 SQL> startup mou ...
- Linux系统-scp简介&坑
文件请见这里: https://blog.csdn.net/xingxingzhilong/article/details/82909015
- Java8中执行js脚本
代码中除了callJSFunctionFromFile函数,其他均转载于文章JDK1.8中如何用ScriptEngine动态执行JS import jdk.nashorn.api.scripting. ...
- (byte & 0xff)操作
先看一段代码: @Test public void test(){ byte a = -5; byte b = 12; System.out.println(a); System.out.printl ...
- 豆瓣读书top250数据爬取与可视化
爬虫–scrapy 题目:根据豆瓣读书top250,根据出版社对书籍数量分类,绘制饼图 搭建环境 import scrapy import numpy as np import pandas as p ...
- PHP功能代码片段
1.连接MYSQL数据库代码 <?php $connec=mysql_connect("localhost","root","root&qu ...
- Asp.net webapi 判断请求参数是否为空简易方法 Model Validation 判断请求参数是否为空
通常情况下,对于那些经常为别人提供数据接口的开发人员来说,对于调用方传递过来的参数都会有验证处理.例如: if (string.IsNullOrEmpty(entity.Name)) { //当姓名为 ...