Redis入门与进阶

Redis 入门与进阶


1、Redis 简介

   Redis 是一个由C语言开发的、开源的、高性能的Key-Value型NoSQL数据库。

  Redis相较于其它 Key-Value 型缓存产品,有如下几个特点:     (1)数据存储在内存里,读写速度很快;
    (2)支持持久化,可以将内存中的数据存储在磁盘中,在重启系统的时候可以重新加载使用;
    (3)丰富的数据类型,有String、list、hash、set、zset(有序集合sorted set)等;
    (4)可以进行主从同步;
    (5)支持数据的备份,即master-slave模式的数据备份。

  Redis常用于缓存,例如记录用户会话信息、记录帖子点赞数、点击数、评论数,缓存文章详情信息等。

2、Redis 安装与配置

(1)Mac 下安装与配置

Mac下安装

  • redis官网下载地址:https://redis.io
    在这里插入图片描述

从终端进入下载后的目录,然后:

  • 解压:tar zxvf redis-6.2.1.tar.gz
  • 移动到:sudo mv redis-6.2.1 /usr/local
  • 切换到:cd /usr/local/redis-6.2.1/
  • 编译测试:make
  • 编译安装:sudo make install

Mac下配置

  • 将 daemonize 后的 no 改为 yes ,表示使用 redis 在后台运行在这里插入图片描述
  • 将 dir 后的 ./ 改为自己所需要的 redis 工作空间
    在这里插入图片描述
  • 将默认的 127.0.0.1 改为 0.0.0.0
    在这里插入图片描述
  • 将 requirepass 后的 foobared 改为自己设置的 redis 的密码,redis 默认不使用密码。注意:记得将本行前的 # 去掉
    在这里插入图片描述
  • 修改 /usr/local/redis-6.2.1/utils/redis_init_script 的 CONF="/usr/local/redis/redis.conf" 配置文件信息
    在这里插入图片描述

Mac下在终端启动 Redis 服务端

  • 回到 /usr/local 目录下,输入 redis-server 回车启动 Redis 服务端
    在这里插入图片描述
  • 扩展:配置开机自启动,配置好之后输入 chkconfig redis_init_script on
    在这里插入图片描述

Mac下在终端启动 Redis 客户端

  启动服务端之后,重新打开另一个终端,输入:redis-cli 就可以进入 redis 客户端。

Mac下在终端关闭 Redis

  输入:shutdown

(2)Windows 下安装与配置

  Windows 下安装点击如下链接见菜鸟教程:https://www.runoob.com/redis/redis-install.html

(3)Linux 下安装与配置

  Linux 下安装点击如下链接见菜鸟教程:https://www.runoob.com/redis/redis-install.html

3、Redis数据类型

(1)Redis通用命令

命令示例说明
selectselect 0选择0号数据库
setset name lily设置key=name,value=lily
getget hello获得key=hello结果
keyskeys he*根据Pattern表达式查询符合条件的key
dbsizedbsize返回key的总数
existsexists a检查key=a是否存在
deldel a删除key=a的数据
expireexpire hello 20设置key=hello 20秒后过期
ttlttl hello查看key=hello的过期剩余时间

(2)String 类型

  String最大512Mb,建议单个K-V不超过100Kb。否则在内存中提取数据的效率很低。

命令示例说明
getget hello获得key=hello的结果
setset hello world设置key=hello,value=world
msetmset hello world java bset一次性设置多个值
mgetmget hello java一次性获取多个值
deldel hello删除key=hello
incrincr countkey值自增
decrdecr countkey值自减
incrbyincrby count 99自增指定步长
decrbydecrby count 99自减指定步长
strlenstrlen key返回 key 所储存的字符串值的长度
appendappend key value如果 key 已经存在并且是一个字符串,append命令将指定的 value 追加到该 key 原来值(value)的末尾

(2)hash 类型

  Hash类型用于存储结构化数据。

命令示例说明
hgethget emp:1 age获取hash中key=age的值
hsethset emp:1 age 23设置hash中的age=23
hmsethmset emp:1 age 30设置hash多个值
hmgethget emp:1 age name获取多个hash值
hgetallhgetall emp:1获取hash所有值
hdelhdel emp:1 name删除emp:1的name
hexistshexists emp:1 name检查key=name是否存在,存在返回1
hlenhlen emp:1获取指定长度
hvalshvals key获取哈希表中所有值
hkeyshkeys key获取key中的所有属性
hincrbyhincrby key field increment为哈希表 key 中的指定字段的整数值加上增量 increment
hincrbyfloathincrbyfloat key field increment为哈希表 key 中的指定字段的浮点数值加上增量 increment

(3)list 类型

  List列表就是一系列字符串的“数组”,按插入顺序排序。List列表最大长度为2的32次方-1,可以包含40亿个元素。

命令示例说明
rpushrpush listkey c b a在右侧依次插入c、b、a
lpushlpush listkey f e d在左侧依次插入f、e、d
rpoprpop listkey在右侧弹出
lpoplpop listkey在左侧弹出
lrangelrange listkey start stop用于输出列表起始到结束的元素
llenllen listkey获取listkey的长度
lindexlindex listkey index通过索引获取列表中的元素
lsetset listkey index value通过索引修改列表元素的值
linsertlinsert listkey beforeafter pivot value
lremlrem listkey count value移除列表元素value,count表示移除的个数
ltrimltrim listkey startindex stopindex对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
deldel listkey删除列表

(4)set 类型

  Set类型里面存放的是无序不重复元素。

命令示例说明
saddsadd myset members向集合添加一个或多个数据
smemberssmembers myset返回集合中的所有元素(重复的数据自动去重)
scardscard myset查看集合中数据的数量
sismembersismember myset member判断某个数据是否在集合中
sremsrem myset members移除集合中的一个或多个元素
spopspop myset [count]移除并返回集合中的一个或多个元素(count是移除的数量)
srandmembersrandmember myset [count]从集合中随机获取count数量的元素
smovsmov set1 set2 member将集合set1中的某个元素member移动到集合set2中
sdiffsdiff set1 set2返回set1与set2中set1独有的元素(差集)
sintersinter set1 set2返回set1与set2中共有的元素(交集)
sunionsunion set1 set2返回set1和set2中的并集

(5)zset 类型

  Sorted Set 存放的是有序不重复元素。每个元素都会关联一个double类型的score,集合通过score对元素进行从小到大排序。集合中的元素是不可重复的,但score却可以重复。

命令示例说明
zaddzadd zset score1 member1 [score2 member2]向有序集合添加一个或多个成员,或者更新已存在成员的分数
zrangezrange zset start stop [withscores]通过索引区间返回有序集合指定区间内的元素,stop为-1表示返回从start开始的所有元素
zrankzrank zset member返回集合中指定元素的索引
zscorezscore zset member返回集合中指定元素的score
zcardzcard zset获取有序集合的元素数量
zcountzcount zset score1 score2返回集合分数区间内的元素数量(左右都是闭区间
zrangebyscorezrangebyscore zset score1 score2 [withscores] [limit offset count]返回指定分数区间内的元素(闭区间)
zrangebyscorezrangebyscore zset (score1 (score2 [withscores]返回指定分数区间内的元素(开区间,有括号“(”表示不包含)
zremzrem zset members移除集合中的一个或多个元素

4、Redis 知识点

(1)Redis 的发布(publish)与订阅(subscribe)

  Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

命令示例说明
publishpublish channel message向某个频道channel发布信息
subscribesubscribe channel [channel …]订阅一个或多个频道
psubscribepsubscribe pattern [pattern …]订阅符合某种匹配模式的频道
unsubscribeunsubscribe channel取消订阅某个频道

(2)Redis 持久化机制之 RDB

  RDB(Redis Database)持久化机制:每隔一段时间(每小时或每天),把内存中的数据写入磁盘的临时文件(默认文件名:dump.rdb),作为快照,恢复的时候把快照文件读进内存。

备份与恢复:
  内存备份 --> 磁盘临时文件
  临时文件 --> 恢复到内存

RDB的优势:

  • 每隔一段时间备份,全量备份;
  • 灾备简单,可以远程传输;
  • 子进程备份的时候,主进程不会有任何io操作(不会有写入修改或删除),保证备份数据的的完整性;
  • 相对AOF来说,当有更大文件的时候可以快速重启恢复。

RDB的劣势:

  • 发生故障是,有可能会丢失最后一次的备份数据;
  • 子进程所占用的内存比会和父进程一模一样,如会造成CPU负担;
  • 由于定时全量备份是重量级操作,所以对于实时备份,就无法处理了。

RDB的配置:

  • 保存位置,可以在redis.conf自定义:/user/local/redis/working/dump.rdb

  • 保存机制:
      save 900 1       -----如果1个缓存更新,则15分钟后备份
      save 300 10        ------如果10个缓存更新,则5分钟后备份
      save 60 10000   ----- 如果10000个缓存更新,则1分钟后备份

  • stop-writes-on-bgsave-error
      yes:如果save过程出错,则停止写操作
      no:可能造成数据不一致

  • rdbcompression
      yes:开启rdb压缩模式
      no:关闭,会节约cpu损耗,但是文件会大,道理同nginx

  • rdbchecksum
      yes:开启使用CRC64进行数据校验,会增加约10%开销
      no:关闭

(3)Redis 持久化机制之 AOF

引子:
  RDB会丢失最后一次备份的rdb文件,但是其实也无所谓,其实也可以忽略不计,毕竟是缓存,丢了就丢了,但是如果追求数据的完整性,那就的考虑使用AOF了。

AOF特点:
  以日志的形式来记录用户请求的写操作。读操作不会记录,因为写操作才会存存储;
  文件以追加的形式而不是修改的形式;
  redis的aof恢复其实就是把追加的文件从开始到结尾读取执行写操作。

AOF的优势:

  • AOF更加耐用,可以以秒级别为单位备份,如果发生问题,也只会丢失最后一秒的数据,大大增加了可靠性和数据完整性。所以AOF可一次,使用fsync操作;
  • 以log日志形式追加,如果磁盘满了,会执行 redis-check-aof 工具;
  • 当数据太大的时候,redis可以在后台自动重写aof。当redis继续把日志追加到老的文件中去时,重写也是非常安全的,不会影响客户端作;
  • AOF 日志包含的所有写操作,会更加便于redis的解析恢复。

AOF的劣势:

  • 相同的数据,同一份数据,AOF比RDB大;
  • 针对不同的同步机制,AOF会比RDB慢,因为AOF每秒都会备份做写操作,这样相对与RDB来说就略低。每秒备份fsync没毛病,但是的每次写入就做一次备份fsync的话,那么redis的性能就会下降;
  • AOF发生过bug,就是数据恢复的时候数据不完整,这样显得AOF会比较脆弱,容易出现bug,因为AOF没有RDB那么简单,但是呢为的产生,AOF就不会根据旧的指令去重构,而是根据当时缓存中存在的数据指令去做重构,这样就更加健壮和可靠了。

AOF的配置:

  • appendonly no
      no:AOF默认关闭
      yes:可以开启

  • AOF的文件名
      appendfilename"appendonly.aof"

  • appendfsync everysec
      no:不同步
      everysec:每秒备份,推荐使用
      always:每次操作都会备份,安全并且数据完整,但是比较慢、性能差

  • 重写的时候是否要同步,no可以保证数据安全
      no-appendfsync-on-rewrite no

  • 重写机制:避免文件越来越大,redis提供了bgrewriteaof指令自动优化压缩,同时会fork一个新的进程去完成重写动作,新进程里的内存数据会被重写,重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

  • 当前AOF文件的大小是上次AOF大小的100%并且文件体积达到64m,满足两者则触发重写
      auto-aof-rewrite-percentage 100(百分比可改)
      auto-aof-rewrite-min-size 64mb(文件大小可改)

到底采用RDB还是AOF呢?

  • 如果你能接受一段时间的缓存丢失,那么可以使用RDB
  • 如果你对实时性的数据比较关心,那么就用AOF
  • 搭配使用:RDB冷备份,AOF热备份

(4)Redis 主(master)从(slave)复制原理

主从复制原理

Redis主从复制可以根据是否是全量分为全量同步和增量同步。

全量同步
  Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

  • 从服务器连接主服务器,发送SYNC命令;
  • 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
  • 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
  • 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  • 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  • 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

  完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。

增量同步
  Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
  增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

Redis主从同步策略
  主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。

搭建主从复制(读写分离)

查看主、从服务器信息的命令: info replication

在从服务器中修改redis的核心配置文件redis.conf的信息:
  配置主服务器IP和端口号:replicaof masterip masterport
  配置主服务器密码:masterauth master-password
  配置主从的读写分离:replica-read-only yes

小知识点:
  当从服务器宕机之后,只要重启宕机的服务器就可将数据进行同步;
  当主服务器宕机之后,从服务器的role依旧是slave不变,但主服务器连接状态为down(即master_link_status:down);
  本质上从服务器是以心跳的方式不断的 ping 主服务器的过程检查主-从服务器之间是否连接。

无磁盘化复制

  主服务器会创建一个新的进程写入一些RDB文件,这些文件是写入到 socket 中,它不用接触到磁盘。当开启无磁盘后,可以配置等待从服务器连接主服务器时间(单位:秒),当时间到了之后开始传输RDB文件。无磁盘化适用于磁盘很慢,但网络带宽很快的情况。

使用无磁盘的配置文件:

  • repl-diskless-sync no
      no:默认是不使用无磁盘化复制(目前无磁盘化属于实验阶段)
      yes:开启无磁盘复制
  • repl-diskless-sync-delay 5
      时间单位为:秒

Redis 缓存过期机制

  redis 缓存可以设置定期的时间,一旦某些key过了定期时间就不能查询,但还会占用服务器的内存。

已过期的key如何处理?
  设置了expire的key缓存过期了,但是服务器的内存还是会被占用,这是因为redis所基于的两种删除策略。

定期(主动)删除
  redis可以定时定期的做检查,它会抽查随机的key,抽查的时间默认 1秒钟10次,一旦抽查到某些key过期,就会将其删除。

  • 设置定期删除时间
      hz 10 (单位为:秒)

惰性(被动)删除
  当客户端请求某个key时,发现其已经过期了,然后才会删除,然后返回一个nil。这种策略友好,不会有太多的损耗,但是内存占用会比较高。

内存缓存淘汰管理机制:MEMORY MANAGEMENT
maxmemory:当内存已使用率到达,则开始清理缓存

  • noeviction:旧缓存永不过期,新缓存设置不了,返回错误
  • allkeys-lru:清除最少用的旧缓存,然后保存新的缓存(推荐使用)
  • allkeys-random:在所有的缓存中随机删除(不推荐)
  • volatile-lru:在那些设置了expire过期时间的缓存中,清除最少用的旧缓存,然后保存新的缓存
  • volatile-random:在那些设置了expire过期时间的缓存中,随机删除缓
  • volatile-ttl:在那些设置了expire过期时间的缓存中,删除即将过期的

LUR:least recently used   最近使用最少
LFU:least frequently used   使用次数最少

(5)Redis 哨兵(sentinel)机制

哨兵启动命令:redis-sentinel sentinel.conf

哨兵机制原理:
  哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。当有一个哨兵发现主服务器宕机时,并不会立即进行 failover操作,当有多个哨兵检测到主服务器宕机之后,那么哨兵之间就会进行一次投票,投票的结果由其中一个哨兵发起并进行failover操作,切换成功后,就会通过发布订阅模式,让各个哨兵把发起failover操作哨兵自己监控的从服务器切换为主服务器。
  仅仅一个哨兵发现主服务器不可用称为主观下线。
  当从服务器切换为主服务器并且其它从服务器更改好主机信息后称为客观下线。

哨兵的作用:

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

哨兵机制文件配置:sentinel.conf

  • 将是否开启保护模式前的“#”去掉。不使用保护模式,这样就能保证其它节点服务器能操作访问哨兵。使用默认端口号。
    在这里插入图片描述
  • 开启后台运行哨兵。将默认的“no”改为“yes”。
    在这里插入图片描述
  • pidfile使用默认
  • 哨兵执行时的日志输出文件:logfile /usr/local/redis/sentinel/redis-sentinel.log
    在这里插入图片描述
  • 哨兵工作目录:dir /usr/local/redis/sentinel
    在这里插入图片描述
  • 修改哨兵名称:lgk-master
  • 哨兵监控的master的内网IP:改为自己的
  • 端口号:使用默认的6379
  • 哨兵的数量:可更改或使用默认的2
    在这里插入图片描述
  • 将昵称mymaster改为和上面自定义的一样:lgk-master
  • 更改密码:将MySUPER–secret-0123password改为自己的密码
    在这里插入图片描述
  • 修改昵称为:mymaster --> lgk-master
  • 修改哨兵认为服务器宕机失效的时间(单位为:毫秒):将其改为10s
    在这里插入图片描述
  • 当某个slave被投票为新的master后,其它slave同步数据的数量(“1”表示一个接一个的同步,“2”表示两个两个的同步 …),使用默认的“1”即可
  • 修改昵称为:mymaster --> lgk-master
    在这里插入图片描述
  • 修改昵称为:mymaster --> lgk-master
  • 哨兵进行故障转移时的超时时间,当其中某个哨兵超时后就会由另一个哨兵进行故障转移。时间使用默认的3分钟即可。
    在这里插入图片描述

(6)Redis 集群(Cluster)

引子
  当master同步数据给slave时,由于是异步复制,假设在复制的过程中,master宕机,slave上的数据可能没有master上的新;当数据同步时,有一定的延时(几百毫秒到一两秒),在这一段时间上的数据有可能丢失,当老的master恢复为slave后,新的数据就会丢失。这些是主从复制或哨兵模式下存在的问题。

Redis 集群
  Redis集群采用去中心化的思想,没有中心节点的说法,对于客户端来说,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单一Redis实例一样,不需要任何代理中间件,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的。
  Redis也内置了高可用机制,支持N个master节点,每个master节点都可以挂载多个slave节点,当master节点挂掉时,集群会提升它的某个slave节点作为新的master节点。

集群配置:

  • 开启集群:将cluster-enabled yes 前的“#”去掉
    在这里插入图片描述
  • 打开集群节点配置文件
  • 打开并设置集群超时时间
    在这里插入图片描述
  • 开启AOF:将“no”改为“yes”
    在这里插入图片描述

注意

  • 删除 /usr/local/redis/working 下的dump.rdb和appendonly.aof两个文件。这两个文件是单机时使用的,集群之后就不能够有或者将这两个文件里面的内容清空,否则在构建集群会报错。
  • rm dump.rdb
  • rm appendonly.aof

构建集群:

  • 查看可用命令:redis-cli --cluster help
  • 命令:redis-cli --cluster create host1:port1 [host2:port2 …] --cluster-replicas args
  • args:表示master与slave的比值
  • 如果显示没有权限,则可以在redis-cli后加-a password(自己的密码)
      redis-cli -a password --cluster create host1:port1 [host2:port2 …] --cluster-replicas args
  • 进入集群的控制台的命令:redis-cli -c -a password -h 要进入的服务器ip -p 6379 (-c表示使用集群模式)
  • 查看集群相关信息:cluster info
  • 查看服务器节点信息:cluster nodes

(7)Redis 在项目中的应用

Redis 单机单实例的配置(.yml)
 redis:
       database:0 (所使用的redis database)
       host: (redis所在服务器的IP)
       port:6379
       password: (redis的密码)

Redis 哨兵模式的配置(.yml)
 redis:
       database:0 (所使用的redis database)
       password: (redis的密码)
       sentinel:
             master:lgk-master
             nodes:host1:port1,host2:port2,host3:port3 … (所用到的master和slave的IP和端口号)

Redis 集群模式的配置(.yml)
 redis:
       password: (redis的密码)
       cluster:
             nodes:host1:port1,host2:port2,host3:port3 … (所用到的master和slave的IP和端口号)

(8)Redis 缓存穿透与雪崩

缓存穿透:
  缓存穿透是指查询一个一定不存在的数据,由于缓存是查不到时就要从数据库里去查询,当查不到数据时就不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

缓存穿透解决方案

  • 如果查询返回的数据为空,则把这个空结果(比如空字符串、空对象、空数组或list)进行缓存,但要设置短的过期时间,最长不超过5分钟。
  • 布隆过滤器:待后续补充!!!

缓存雪崩
  数据进行缓存时会设置过期时间,一旦过期时间重合,某个时刻大量的key同时到达过期时间,同时失效,而此时恰恰有很大的流量进来,此时所有的请求都会冲击数据库,就会造成数据库的崩溃,这就是缓存雪崩。

缓存雪崩的预防措施

  • 永不过期
  • 过期时间错开
  • 多种缓存结合
  • 采购第三方 redis

5、Redis 常见面试题

1、Redis是什么?都有哪些应用场景?

  答:Redis是一个使用C语言开发的高性能Key-Value型NoSQL数据库。支持的数据类型有String、list、hash、set、zset(有序集合sorted set)等(范围查询)。Redis常用于缓存,例如记录用户会话信息、记录帖子点赞数、点击数、评论数,缓存文章详情信息等。

2、Redis持久化有几种方式?Redis是如何做持久化的?

  答:Redis有两种持久化方式,RDB(Redis Database):指定时间间隔对数据进行快照存储;AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。
  bgsave做镜像全量持久化,AOF做增量持久化。因为bgsave会耗费较长的时间,实时性不够好,在停机的时候会导致大量的数据丢失,所以需要配合AOF来使用;在Redis重启时,会使用bgsave持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现恢复重启前的状态。

(如果机器突然断电会怎样? 取决于AOF日志sync属性的配置,如果不要求性能,可以在写每条指令是都sync一下磁盘,这样就不会丢失数据,但在高性能条件下一般会使用定时的sync,比如1秒一次,这样就算断电,也只会丢失一秒的数据而已。

bgsave的原理是什么? 是fork和cow。fork是指Redis通过创建子进程来进行bgsave操作,cow是copy on write,子进程创建后,父进程共享数据段,父进程继续提供读写服务,写脏的页面数据就会逐渐和子进程分离开来。)

3、怎么保证缓存和数据库的数据的一致性?

  答:可以使用事务机制来对数据库进行增、删、改操作时同步更新Redis缓存。

4、Memcache与Redis有什么区别?

答:

  • 存储方式不同:Memcache把数据全部存在内存之中,断电后会挂掉,而且数据不能超过内存大小;Redis会把部分数据存储在硬盘上,这样就能保证数据的持久性。
  • 数据支持类型不同:Memcache支持的数据类型相对简单,而Redis有复杂的数据类型。
  • 使用的底层模型不同:它们之间的底层实现方式以及与客户端之间通信使用的协议不一样。因为一般系统在调用系统函数时会浪费一定的时间去移动和请求,所以Redis直接构建了自己的VM机制。

5、Redis的同步机制了解吗?

  答:Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存,加载完成,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

6、Redis怎么实现分布式锁?分布式锁有什么缺陷?如果在执行setnx之后expire之前进程出现意外,那会怎么样?

  答:Redis使用setnx(set if not exit)指令来争抢锁,抢到之后再用expire给锁加一个过期时间防止锁忘记释放。

  Redis分布式锁不能解决超时的问题,所以要设置一个过期时间。

  因为set指令有非常复杂的参数,所以可以同时把setnx指令和expire指令合成一条指令来执行。

7、Redis为什么是单进程单线程的?

  答:因为CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存或网络带宽。Redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。

8、Redis集群的原理是什么?

  答:Redis Sentinal(哨兵)关注高可用,在master宕机时会自动将slave(从动装置)提升为master继续提供服务。Redis Cluster(集群)关注扩展性,在单个Redis内存不足时,使用Cluster进行分片存储。

9、什么是缓存穿透?怎么解决?

  答:缓存穿透是指查询一个一定不存在的数据,由于缓存是查不到时就要从数据库里去查询,当查不到数据时就不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
  解决方案:如果查询返回的数据为空,则把这个空结果进行缓存,但要设置短的过期时间,最长不超过5分钟。

10、假如Redis里面有1亿个key,其中有10w个key是以某个固定的前缀开头,如何将他们全部找出来?如果这个Redis正在给线上的业务提供服务,那么使用keys指令会出现什么问题?

答:使用keys指令可以找出指定模式的key列表。
  由于Redis是单线程的,keys指令会导致线程阻塞一段时间,线上服务会停顿指导keys指令执行完毕服务才能恢复。这个时候可以使用scan指令无阻塞的提取出指定模式的key列表,但会有一定的重复率,可以在客户端做一次去重。scan指令所花费的时间整体上会比直接使用keys指令长。

11、Redis常见的性能问题以及解决方案?

答:

  • Master写内存快照,save命令调度RDBSave函数,会阻塞主线程的工作,当快照比较大时对性能的影响非常大,会间断性暂停。所以Master最好不要写内存快照。
  • Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启时的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF内存文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个slave开启AOF备份数据,时间为每秒同步一次。
  • Redis主从复制性能问题。为了主从复制的速度和连续的稳定性,Slave和Master最好在同一个局域网内。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值