前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis全面总结

redis全面总结

作者头像
小土豆Yuki
发布2021-02-01 10:45:28
3550
发布2021-02-01 10:45:28
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗
  1. redis是什么 redis是c语言开发的一个开源的高性能键值对的内存数据库,一个内存中的数据结构存储系统,他可以用做数据库,缓存,消息中间件.支持多种类型的数据结构,如字符串,列表,哈希,集合,有序集合,bitmaps,Hyperloglogs,geo(地理空间) 字符串,是redis的基本类型,一个key对应一个value,最大可以存储512M,常用的命令有set,get,mget等,应用场景微博数,粉丝数 列表,是一个字符串列表,按照插入的顺序排序,是一个双向链表,支持反向查找和遍历,常用命令lpush,rpush,lpop,rpop,lrange等命令,使用场景关注列表,好友列表等 哈希,和我们java中的hashmap类似,hash特别适合存储对象常用命令,hget,hset,hgetall等,应用场景可以存储用户的信息商品的信息等, set,是一种无序集合,支持去重操作,但没有顺序,常用命令,sadd,spop,smemebers,sunion操作,方便集合之间的操作,引用场景,判断某个元素是否存在set集合中 zset,和set类似,且有序,使用一个额外的参数score为成员排序,内部使用hashmap和跳跃表实现存储和有序,HaspMap存放成员到score的映射,而跳跃表存放所有的成员,使用跳表实现比较高的查询效率,常用命令zadd,zrange,zrem,zcard等待,使用场景用分数进行成员的从小到大的排序 bitmaps(位图),实际上就是字符串,但是他可以对字符串的位进行操作,可以把位图当做一个以位为单位的数组,数组中只有0或1,如[00111010010010...],数组的下表就是偏移量,最大长度是512M,即2^32个比特币,常用命令setbit ,getbit,bitcount,使用场景,如用户的打卡,网站的浏览次数等等,(如果我们使用String记录用户的打卡,当用户量非常大的时候,就会占用内存,但是使用位图,一年365天相当于365bit,1字节=8bit,也就46字节而已,比如setbit user1 0 1表示user1第一天打卡成功,setbit user1 1 0表示user1第二天打卡失败) Hyperloglogs,提供一种不太准确的基数统计算法(统计一批数据中的不重复的个数),常用命令pfadd,pfcount,pfmerge等等,使用场景网页的UV(用户访问网站的次数) geospatial(地理空间),把指定的地理空间位置添加到指定的key中,如geoadd city 116.40 39.9 北京(geoadd key longitude latitude member),常用命令geoadd,geopos,geodist,georadius使用场景,计算两点之间的距离,查看指定位置附近范围的人.
  2. redis雪崩,缓存穿透,击穿是什么意思,如何解决 redis雪崩,我们认知的缓存都是存储热点数据,我们查询数据,先去缓存查找,如果缓存不存在,就直接到数据库查找,但是有一种情况我们要注意,比如,我们把缓存的key的有效时间是晚上0点,然而再0点正好有一次大促销活动,假设0点的请求量为8000请求/秒,同时所有的key失效了,因此8000个请求直接落到了数据库,此时数据库还没有反映过来,就直接过了,这就是雪崩。 如果遇到这种情况,我们可以给redis存储的数据设置一个随机事件,而不是设置同一时刻,这样就可以保证不会大面积失效,当然如果redis是集群,可以把热点数据分布在不同的redis库中也能避免全部失效,最暴力的就是不设置过期时间,更新操作在修改缓存就可以了 缓存穿透,其实就是缓存和数据库都没有数据,此时有大量的请求,获取不存在的数据,如我们数据的id都是大于1的值,但是黑客使用id=-1的请求不断的攻击,导致数据库压力过大,严重的时候会导致数据挂掉 如果遇到这种情况,我可以给请求入参添加校验,只有合法的参数才能请求服务,也可以利用布隆过滤器,当不存在的时候就必要查询请求了。 缓存击穿,是指一个大热点key,百万级用户不断请求,但是在某一刻失效了,也会导致大量请求到数据库,导致数据库挂掉, 如果遇到这种情况,我也可以设置缓存不过期,或者使用分布式锁。
  3. redis是单线程吗,为什么这么快 resi是单线程,但是官方声称redis的QPS可达100000+,为什么是单线程还这么快,如下原因
    1. redis基于内存,所有数据都在内存中,类似hashMap,时间复杂度为O(1)
    2. 数据结构简单,对数据操作也简单
    3. 使用单线程,避免了不必要的上下文切换和竞争条件不存在多线程的CPU切换,也不存在加锁释放锁操作。
    4. 使用多路复用IO模型,非阻塞IO.
  4. redis和memcached有什么区别
    1. redis可以持久化,而memcached数据全部在内存中
    2. redis支持多种数据结构,memcached支持key-value
    3. 使用的协议不一样,memcached的客户端通过TCP连接服务器通信,redis使用RESP协议通信,是专门为Redis设计的通讯协议,redis直接构建自己的VM机制,因为一般的系统调用系统函数,会浪费一定的时间去移动和请求.
    4. value的大小,redis可以达到1GB,而memcached只有1MB
  5. Redis的淘汰策略有哪些 策略 描述 volatile-lru 从已设置过期时间的KV集中,优先对最近最少使用的淘汰 volatile-ttl 从已设置过期时间的KV集中,优先对剩余时间短的数据进行淘汰 volatile-random 从已设置过期时间的KV集中,随机选择数据淘汰 volatile-lfu 从已设置过期时间KV集中,优先选择最不经常的数据进行淘汰 allkeys-lru 从所有KV集中,优先对最近最少的数据进行淘汰 allkeys-random 从所有KV集中,随机选择数据淘汰 allkeys-lfu 从所有kV集中,最不长用的数据进行淘汰 noeviction 不淘汰,直到超过最大内存,返回错误信息
  6. redis的持久化有几种 redis的持久化操作有两种,一种是RDB,RDB是以快照形式直接把内存的数据保存在一个dump文件中,而另外一种AOF,是把每一次修改命令存储在文件里,redis默认是RDB持久化方式,但是在重启的的时候,他会优先使用AOF,因为AOF保存的数据比RDB更加完成, RDB触发的方式
    1. 手动触发,使用save,bgsave命令
      1. save会阻塞redis服务器进行直到RDB文件创建完毕之后,否则服务器在这期间一直阻塞,而bgsave是会fork一个子进程,有子进程负责创建RDB文件,而父进程会继续处理请求。
    2. 自动触发,通过配置文件的命令save m n,满足下面任何一个条件如
      1. save 900 1,到900秒内的时候,如果redis至少发生一次变化
      2. save 300 10,到300秒内,至少发生10变化
      3. save 69 10000,到10000秒内,知道发生10000变化
    3. 其他原因如主从复制场景,从节点执行全量复制操作,或执行shutdown命令时,都会执行RDB持久化
  7. redis中bgsave执行流程
  1. redis父进程判断是否有执行save,bgsave,bgrewriteaof的子进程,如果在执行则bgsave命令直接返回,
  2. 父进程执行fork操作创建子进程,这个过程父进程阻塞,redis不能执行客户端的任何命令
  3. 父进程fork后,bgsave命令返回"backgroud saving started"信息并不再阻塞父进程,并可以相应其他命令
  4. 子进程创建RDB文件,根据父进程内存快照生成临时文件,完成对原来文件的替换
  5. 子进程发送信号给父进程表示完成,父进程更新统计信息
  1. AOF运行原理

开启AOF,需要在配置文件中配置appendonly yes,而AOF执行流程包括下面三种

  1. 命令追加,将redis的写命令追加到缓冲区aof_buf
  2. 文件写入和文件同步,根据不同的同步策略将aof_buf的内容同步到磁盘
  3. 文件重写,定期重写AOF文件,达到压缩的目的

命令追加

redis是将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次写命令直接写入磁盘,导致硬盘IO成为redis负载的瓶颈

文件写入和文件同步

为了提高文件写入的效率,在现在操作系统中,当用户调用write函数将数据写入文件的时候,操作系统通常将数据暂存到一个内存缓冲区里,当缓冲区慢了或者超过了指定大小后,才会将内存缓存区中的数据写入到内存,这样虽然提高了效率,但是存在安全问题,比如计算机停机,内存缓存区的数据就会丢失,因此操作系统提供了文件同步的同步函数fsysnc,fdatasync函数,可以强制把操作系统立刻将缓存区中的数据写入到硬盘里,从而保证数据的安全性,文件同步策略的策略由参数appendfsync控制

代码语言:javascript
复制
appendfsync always,
//命令写入aof_buf后立刻调用系统fsync操作同步到AOF
appendfsync no
//命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,
//此时的同步有操作系统负责,通常同步周期30s
appendfsync everysec
//命令写入aof_buf后调用系统write操作,write完成后线程返回,fsync同步文件操作由专门
//的线程每秒同步一次

文件重写

文件重写是指定期重写AOF文件,减少AOF文件的体积,重写就是把redis中的数据转成写命令,同步到AOF文件,不会对旧的AOF文件进行任何读取写入操作。具体的操作流程

  1. redis父进程判断是否存在bgsave/bgrewriteaof的子进程,如果存在就直接返回,
  2. 父进程fork出子进程,这个过程父进程阻塞
  3. 父进程fork后,bgrewriteaof命令就返回"Background append only file rewrite started",此时父进程不在阻塞,同时redis客户端写命令写入AOF缓存区,并根据同步策略同步到旧的AOF文件
  4. 在上图中3.2步骤,在子进程生成新的AOF文件的同时,新的命令会同时写入aof_rewrite_buf中,这样就可以防止数据丢失,
  5. 子进程根据内存的快照,按照命令合并规则写入新的AOF文件
  6. 子进程完成新AOF文件后,就会通知父进程,父进程更新统计信息,
  7. 在5.2步骤,父进程会把aof_rewrite_buf的数据写入到新AOF文件,这样就保证了新的AOF保证了数据的完成性
  8. 最后使用新AOF文件替换旧的AOF文件
  1. RDB和AOF的优缺点 命令 RDB AOF 启动优先级 低 高 体积小大 恢复速度 快慢 数据安全性 丢数据 根据策略决定 轻重 重 轻
  2. 如何选择RDB和AOF持久化策略

两种持久化策略持久化都是有性能代价的,RDB持久化,在使用bgsave的时候会阻塞主进程,子进程向硬盘写数据会带来Io压力,AOF持久化,向硬盘写数据的频率越大,IO压力更大,甚至导致AOF阻塞问题,

而在实际场景,根据数据量,应用数据安全的要求,预算限制等不同情况,会有各种各样的持久化策略,我们可以单独用一种策略,也可以两种混合使用.

如果数据完全对丢失数据对业务没有任何影响,就可以不进行任何持久化如果在单机情况,如我们自己练习,如何可以接受丢失数据,可以使用RDB,如果只能接受秒级别的数据丢失,可以选择AOF

如果是我们的生产环境,主从环境,一般我们可以master关闭持久化,可以在slave关闭RDB,开启AOF,然后关闭自动重写,添加定时任务,定时调用bgrewriteaof

上面只是简单的举例,所以如果你可以接受几分钟你的数据丢失,那么可以使用RDB,否则可以使用AOF持久化,但是AOF每一条命令追加磁盘,会降低redis性能,对于数据备份和灾难恢复,定时生成RDB快照非常便于进行数据库备份,但是RDB的回复数据集的速度比AOF恢复速度快,如果混合持久化,AOF重写的时候就直接把RDB的内容写到AOF文件开头,这样做的好处是可以结合RDB和AOF的优点,快速加载同时避免丢失过多的数据,当然AOF里面的RDB部分是压缩格式不再是AOF格式,可读性差.

  1. redis主从复制过程 主从模式结合哨兵模式能够解决掉单点模式,提高redis可用性,从节点仅提供读服务,而主节点提供些操作,对于读多写少的情况,可以从节点的数量,从而提高响应效率,而主节点和从节点直接的复制过程如下
    1. 从节点执行slave masteip masterPort.保存主节点信息
    2. 从节点的定时任务发现主节点信息,建立和主节点的socker链接
    3. 从节点发送ping信号,主节点返回pong,两边就能互相通讯
    4. 连接建立以后,主节点将所有数据发送给从节点进行数据同步
    5. 主节点把当前的数据同步给从节点后,便完成了复制的建立过程,接下来,主节点就会持续把写命令发送给从节点,保证主从数据一致性。
  2. 主从复制的原理

redis2.8之前使用的sync runid offset同步命令,redis2.8之后使用的psync runid offset命令,连个都是同步的命令,但是sync仅支持全量同步,而psync支持全量同步和增量同步,

runid:每个redis节点都有一个唯一的id,且每次重启都是重新生成

offset:主节点和从节点各自维护自己的主从复制的偏移量offset,当主节点写入命令时候,会记录offset=offset+命令字节长度,从节点在收到主节点发送的命令后,也会记录自己的offset,并把自己的offset同步给主节点,这样主节点保存自己的和从节点的offset,通过对比就可以知道数据是否一致

repl_backlog_size:保存在主节点的一个固定长度的先进先出的队列,默认大小是1MB

  • 主节点发送数据给从节点过程中,主节点还会进行一些写操作,这个时候数据就会写入复制缓存区中,从节点完成主节点数据同步后,主节点将缓存继续发送给从节点,用于部分复制
  • 主节点不但会把写命令发送给从节点,而且会写入复制缓冲区,用户复制命令丢失的数据补救

全量复制的过程和部分复制过程如下图

全量复制的主要步

  1. 从节点发送psync ? -1命令,第一次发送,不知道主节点的runid因此使用?,且默认offset=-1
  2. 主节点发现是第一次复制,返回FULLRESYNC runid offset,runid是主节点的runid,offset是主节点的offset
  3. 从节点接收到主节点的信息,保存到info中
  4. 主节点发送FULLRESYNC后,启动bgsave命令,生成RDB文件进行持久化
  5. 主节点发送RDB文件给从节点,到从节点加载数据完成期间,主节点会把写命令放到缓冲区中
  6. 从节点清理自己的数据库数据
  7. 从节点加载RDB文件,将数据保存在自己的数据库中
  8. 如果从节点开启了AOF,从节点异步重写AOF文件

增量复制过程如下

  1. 当出现网路抖动,超过了连接时间,主从就会断开连接
  2. 但是在这期间主节点还会接受到命令,会把命令写入到复制缓冲区中(repl-bacjlog-buffer)
  3. 当网络恢复以后,从节点会主动再次连接
  4. 从节点发送psync runid offset,runid是当前自己的runid,offset是主节点给他偏移量
  5. 主节点接受到从节点的runid,和offset,会进行核对,其中master如果发现偏移量在复制缓冲区中,根据offset查找复制缓存的数据,且对从节点发送continue表示可以继续部分复制
  6. 主节点把缓存中的数据发送给从节点,保证主从的数据保持一致
  1. 主从复制会有什么问题
    1. 一旦出节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还要使用命令使所有的从节点去复制新的主节点,整个过程需要人工干预
    2. 主节点的写能力受到单机的限制
    3. 原生复制在复制中断后,从界定会发起psync,此时如果同步不成功,则进行全量复制,期间会导致短暂的停顿
  2. 如何解决主从复制的问题 当然我可以使用哨兵模式,下图就是就是哨兵模式

如图,是哨兵的架构图,哨兵的主要功能就是主从节点存活检测,主从运行情况检测,自动故障转移,主从切换,可以执行以下四个任务

  • 监控,不断检查主服务器和从服务器是否正常运行
  • 通知,当redis服务器出现问题,哨兵通过api通知管理员发出通知
  • 自动故障转移,当主节点不能正常工作的时候,sentinal就会开启一次自动故障转移操作,会把其中一个从节点晋升为新的主机节,且会把其他从节点重新指向新的主节点,不需要任何人为干预
  • 配置提供者,在哨兵模式下,客户端在初始化的时候链接的是sentine节点,从中获取主节点的信息

  1. 哨兵原理

上图就是一张哨兵的架构图,我接着说他是如何工作的

  1. 每个sentinel节点都需要定期执行向所有主从服务器以及其他sentinel实例发送ping命令
  2. 但是当主节点最后一次回复ping命令超过了设置的时间(down-after-milliseconds参数指定的值),那么就会认为这个节点主观下线
  3. 如果一个主服务器被标记为主观下线,此时全部的sentinel节点都会每秒一次的频率确认主服务器的确是否进入主观下线状态
  4. 此时大多数sentinel确认主服务器为下线,那个这个主服务器标记为客观下线
  5. 正常情况下,每个sentinel会以每10秒一次的频率向已知的所有主从服务器发送info命令,但当一个主服务被标记为客观下线时,sentinel就会把info命令的频率改为每秒一次
  6. sentinel和其他sentinel协商客观下线的主节点状态,如果处于sdown状态则重新投票选出新的主节点,将剩余的节点指向新的节点进行数据复制
  7. 但是如果没有足够sentinel认为主服务下线时候,主服务器的客观下线状态就会移除,同时当主服务器的ping命令返回有效的恢复时候,就会移除主观下线。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档