redis知识点3.0

为什么经常会有某些大型购物商城翻车

罪魁祸首——关系型数据库

-性能差,需要经常与磁盘进行交互

-扩展性差,数据之间关系复杂,查询起来很慢

解决思路

-提高性能,降低与磁盘交互的次数——内存存储

-提高扩展性,去除数据之间的关系——不存储关系,仅存储数据

Nosql应运而生

redis

redis是一个由C语言开发而成的一个高性能键值对(key-value)数据库

特点:

-高性能,数据存储在内存(但第一次访问数据的时候依然会去磁盘里面读)

-扩展性好,数据之间没有必然的关系

-多数据类型支持,string,list,hash,set,sorted_set,bitmap(以bit为单位的操作),hyperlog(基于基数的数据结构),geo(操作地理信息的)

-内部采用单线程机制进行工作(因此适合并发操作)

-持久化存储数据,可以进行数据灾难恢复

redis的线程模型

redis是通过文件事件处理器来处理的,因为文件事件处理器是单线程的,所以redis才叫单线程模型

文件事件处理器包括四个部分:

1)多个socket

2)IO多路复用程序

3)文件事件分派器

4)事件处理器(包括连接应答处理器、命令请求处理器、命令回复处理器)

大概处理过程:

IO多路复用程序同时监听多个socket并将socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,并把事件交给对应的事件处理器进行处理
在这里插入图片描述
为什么redis单线程模型效率也很高

1、纯内存操作

2、核心是基于非阻塞的IO多路复用机制(可以不断的从socket拿去事件然后放到队列里)

3、单线程反而避免多线程的频繁上下文切换问题

redis的应用场景

1、热点数据(访问量数据特别大的)的缓存

2、限时业务操作

通过一个expire命令可以设置一个键的生存时间,利用这一特性可以用在限时优惠活动或者手机验证码

3、计数器相关问题

redis通过incrby命令可以实现原子性的递增,高并发的秒杀活动

decrby可以用来原子性递减

4、排行榜相关问题

可以借助redis的sortedset进行热点数据的排序

5、分布式锁

主要利用setnx命令进行,setnx的意识即是set if not exists,如果不存在则设置缓存。

我们可以先通过setnx命令设置一个lock,如果成功设置那么将执行,如果没有成功设置,则表明该任务已执行了,我们可以给lock设置一个过期时间,结合过期时间是防止死锁的出现

6、点赞、好友等相互关系的存储

利用set存储用户之间的点赞关联,另外在点赞钱就进行是否点赞过

sismember key member

7、队列

redis里的list有push 和pop这样的命令,方便执行队列操作

redis的数据类型

8种,数据类型指的是value部分,key部分永远都是字符串

string-String,hash-HashMap,list-LinkedList,set-HashSet、sorted_set-TreeSet

string类型

存储单个数据,是最简单的数据存储类型,通常使用字符串,当遇到incr和decr时会自动转成数值型进行计算,转换不成功或超过redis的数值上限会报错,适合用来存储属性

//单个key对象
set key value
get value
del key
//多个key对象
mset key1 value1 key2 value2 ...
mget key1 value1 key2 value2 ...
//获取字符串长度
strlen key 
//追加信息到原始信息后面,如果存在就追加,否则新建
append key value 
//string的扩展操作——给value增值或减值
//为key储存的数字值+1,如果key不存在,那么值会被初始化为0,如果key储存的值不能被解使为数字,那么将会报错
incr key 
set num 10
incr num
get num -->num=11

incrby key increment 
incrby num 5 
get num -->num=15
//小数点增加
incrbyfloat key increment 
incrbyfloat num 5.20
get num --> num=15.20
//减值
decr key
decrby key increment
//string类型的扩展操作——设置数据的生命周期
setex key seconds value
psetex key milliseconds value

string的应用场景

存储某些高频访问的信息,例如微博里的粉丝数

hash类型

一个value的存储空间可以存储多个键值对,适合用来存储对象

hash存储结构优化

-如果field数量少,存储结构优化为类数组结构

-如果field数量多,存储结构使用hashmap

操作命令

添加/修改数据
单个key对象
hset key field value
hget key field
hgetall key
hdel key field1 [field2]
多个key对象
hmset key filed1 value1 field2 value2 ...
hmget key filed1 filed2
获取字段数量
hlen key
是否存在指定字段
hexists key field
扩展操作
获取所有字段名
hkeys key
获取所有字段值
hvals key
增值
hincrby key field increment
hincrbyfloat key field increment

注意事项

-hash类型下的value只能存储字符串,不存在嵌套现象

-hgetall可以获取全部属性,但是如果field过多,效率会很低

hash的应用场景

某东电商购物车部分设计

list类型

保存多个数据,会有顺序先后,底层采用双向链表结构进行存储

基本操作

添加/修改数据
将一个或多个数据插入到表头,即最左边
lpush key value1 value2 ...
将一个或多个数据插入到表尾,即最右边
rpush key value1 value2 ...
获取数据
lrange key start stop
lindex key index
llen key
移除并获取元素值
第一个元素
lpop key
最后一个元素
rpop key
扩展操作
移除指定数据
lrem key count value
当count >0时,从表头向表尾进行搜索,移除与value相等的元素,数量为count
当count <0时,从表尾向表头进行搜出,移除与value相等的元素,数量为count的绝对值
当count=0时,移除表种与value相等的所有值

业务场景

朋友圈点赞,微博关注列表

set类型

查询效率更高,与hash存储结构完全相同,但仅存储键,不存储值,并且键不允许重复

基本操作

sadd key member1 member2 
获取所有数据
smembers key
删除数据
srem key member1 member2
获取集合数据总量
scard key
判断集合中是否包含指定数据
sismember key member
扩展操作
随机获取集合中指定数量的数据
srandmember key [count]
随机获取集合中的某个数据并将该数据移出集合
spop key [count]
求两个集合的交、并、差集
sinter key1 key2
sunion key1 key2
sdiff key1 key2
求两个集合的交、并、差并存储到指定的集合中destination 
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2]
将指定数据从原始集合中移动到目标集合中
smove source destination member

应用场景

随机挑选部分热点新闻并推荐给用户

也可以用来显示共同关注

注意事项

set类型不允许数据重复,如果已存在,将只保留一份

sorted_set类型

在set的存储结构基础上添加可排序的字段

zadd key score1 member1 [score2 member2 ]
zrange key start stop [withscores]
zrevrange key start stop [withscores]从大到小排序
zrem key member1 [member2]删除数据
按条件获取数据
zrangebyscore key min max [withscores] [limit] 从小到大
zrevrangebyscore key max min [withscores] 从大到小
条件删除数据
zremarangebyrank key start stop
zremrangebyscore key min max
获取集合数据总量
zcard key
zcount key min max
集合交、并操作
zinterstore destination numkeys key [key ...]
zunionstore destination numkeys key [key ...]
扩展操作
排位赛,票选十大青年
获取数据对应的索引(排名)
zrank key member
zrevrank key member
score值获取与修改
zscore key member 获取
zincrby key increment member 修改

key的通用操作

key是一个字符串,通过key可以获取redis中保存的数据

del key 删除
exists key 是否存在
type key 查询key的类型
key的时效性控制
设置key的有效期
expire key seconds 设置存活的时长
expire key milliseconds
expireat key timestamp 设置存活到哪个时间戳
prxpireat key milliseconds-timestamp
获取key的有效时间
ttl key
pttl key
将key从时效性转成永久性
persist key
key的模糊查询操作
*匹配任意数量的任意符号
?匹配一个任意符号
[]匹配括号里的一个指定符号
keys * 查询所有
keys it* 匹配所有以it开头
keys *heima 匹配所有以heima结尾
keys ??heima 匹配所有前两个字符任意,后面以heima结尾的
keys user? 匹配所有以user开发,最后一个字符任意的
keys u[st]er 查询所有以u开头,以er结尾,中间包含一个字母,s或t的
key其他操作
为key改名
rename key newkey
renamenx key newkey 仅当newkey不存在时将key改为newkey

redis的数据持久化

概念:利用永久性存储介质将数据进行保存,在特定的时间对保存的数据进行恢复的工作机制就叫做持久化

作用:防止数据丢失,确保数据的安全

redis的持久化类型

-RDB,数据同步,以快照的形式将当前(所有)数据结果进行保存

-AOF,指令同步,以日志的形式将当前数据的操作过程进行保存

RDB的相关命令

启动——save指令

作用

save命令执行一个同步保存操作,该命令会把当前所有数据快照以二进制RDB形式保存到硬盘

save过程

save指令直接调用rdbsave,阻塞redis主进程,直到指令执行完毕

在主进程阻塞期间,不能处理客户端任何请求,因此线上不建议使用

save的自动保存指令配置
save second changes
在seconds时间内key的变化数量达到指定数量即进行持久化
changes为监控key的变化量
该配置可以在redis.conf里配置
范例:
save 900 1900s内有一个发生变化即进行保存

启动——bgsave指令(save的优化版)

作用:

不会阻塞服务器,在后台将当前所有数据快照以二进制RDB的形式保存到硬盘,不会阻塞服务器

bgsave的过程

bgsave指令执行之后立即返回ok,然后系统调用fork函数生成一个子进程

原来的父进程继续处理客户端请求,而子进程负责将数据快照以RDB的形式保存到磁盘

save和bgsave的区别

save:save是同步保存指令,在执行的过程中会阻塞服务器,此时服务器不会执行任何指令

bgsave:通过创建子进程在后台执行保存操作,此时服务器可以执行其他指令(但是不会再执行save和bgsave指令)

由于需要创建新的子进程,因此需要牺牲一些性能

rdb特殊的启动形式

1、全量复制

全量复制是主从复制的一种,其原理是master服务器会开启后台进程生成rdb文件

与此同时服务器会缓存所有来自客户端的写命令

当rdb文件生成完毕后,会将rdb文件传给slave服务器,而slave会将rdb文件保存并加载到内存

master会将缓存的指令传给slave,然后slave再执行这些指令以保证数据的统一性

2、关闭服务器时指定保存数据

为了保证数据不丢失

shutdown save

3、服务器运行过程中重启

为了保证数据不丢失

debug reload

因此RDB的启动方式有五种

RDB优点

-体积更小,相同数据量rdb数据比aof更小,因为rdb是紧凑型的

-恢复更快,rdb是数据的快照,其实就是数据的复制,不用重新读取再加入到内存

RDB缺点

-数据丢失,如果rdb执行指令是设置save 900 20这样的话,那么如果条件没满足且宕机了,那么将会丢失数据

-rdb持久化时,如果文件过大可能会导致服务器阻塞,停止客户端请求

当是save指令时,则会阻塞服务器

应用

灾难恢复,可以每小时备份一次rdb文件,当遇到问题,随时还原数据

AOF的相关指令

指令同步,以日志的形式将当前数据的操作过程进行保存,目前比较主流

aof写数据的三种策略

-always:每次写入操作都同步到aof文件中,数据零误差,性能较低

-everysec:每秒将缓冲区中的指令同步到aof文件中,准确性高,性能高,如果系统宕机那么将会丢失一秒的数据

-no:由操作系统自己决定什么时候进行指令同步,不可控

aof的优缺点

优点

1、数据保证,如果设置的同步策略时everysec,那么最多丢失1秒的数据

2、自动缩小,当aof文件达到一定程度时会自动重写aof文件

缺点

1、体积相对较大,毕竟保存的是操作的过程

2、恢复速度更慢

aof配置

开启功能(默认不开启)
appendonly yes
同步指令的策略,写数据策略
appendfsync always|everysec|no
持久化文件名,默认文件名为appendonly.aof,建议配置成appendonly-端口号.aof
appendfilename filename
持久化文件保存路径,与rdb持久化文件保持一致即可
dir

aof重写机制

随着命令不断写入aof,文件越来越大,redis通过aof重写机制压缩文件体积

简单来说就是从数据库中读取键的值,然后用一条命令去记录键值对代替之前多条命令记录键值对

重写的作用

-降低磁盘(空间)占用量

-降低持久化写入时间(如果需要进一步重写)

-降低数据恢复时间

aof重写规则(aof文件为什么可以变小)

-只保存最终数据结果所对应的指令

例如set key 111 set key 222,最后只保存set key 222

-对同一数据的多条命令合并为一条命令(例如对一个list,lpush多条数据)

例如:lpush list1 a、lpush list1 b -> lpush list1 a,b

-进程内已超时数据的指令将不再写入文件(过期或者已经被删除的数据)

aof重写方式

-手动重写

bgrewriteaof

-自动重写

通过监控aof文件的大小或者存储比例来判断是否重写

自动重写规则

auto-aof-rewrite-min-size size 即aof文件达到size大小才会进行重写

auto-aof-rewrite-percentage percentage 即aof文件增长比例达到多少才会进行重写

bgrewriteaof 重写工作原理

收到 bgrewriteaof 命令时,Redis 调用 fork函数构建一个子进程(避免使用主进程导致服务器阻塞)

子进程在进行AOF重写期间,主进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致

为了解决这个问题,Redis增加了一个AOF重写缓存,Redis主进程在接到新的写命令之后,除了会将这个写命令的内容追加到现有的AOF文件之外,还会追加到这个缓存中

当子进程完成对AOF文件重写之后,它会向父进程发送一个完成信号,父进程接到该完成信号之后,会调用一个信号处理函数,该函数完成以下工作:

1)、将AOF重写缓存中的内容全部写入到新的AOF文件中;

2)、对新的AOF文件进行改名,覆盖原有的AOF文件

最后这两个步骤会阻塞主进程

旧的aof文件在bgrewriteaof执行成功之前依然存在,达到备份的目的

aof缓冲区和aof重写缓冲区

aof缓冲区:是正常写入指令到aof文件中的中间地带,当写入速度较慢时,数据就会先再aof缓冲区存着,然后再同步到aof文件里去

aof重写缓冲区:是aof重写过程中,主进程还再继续接收数据,那么这些数据就会存储到重写缓冲区里

当重写完成后,再将缓冲区里的数据同步到临时aof文件里

最后临时aof文件替换旧的aof文件并重新命名

RDB和AOF的区别

RDB的存储空间小,aof存储空间大

rdb存储速度慢,恢复速度块,aof存储速度快,恢复速度慢

rdb会丢失数据,aof根据策略决定

RDB和AOF应该如何选择

1、不要仅仅使用rdb,因为那样可能会丢失很多数据

2、不要仅仅使用aof,使用aof做冷备(一台服务器运行,一台用来备份),没有rdb做冷备恢复速度快;

rdb生成的数据快照更加健壮,可以避免aof复杂的备份和恢复机制bug

3、综合使用aof和rdb,aof来保证数据不丢失,rdb来做不同程度的冷备

当aof文件丢失或损坏不可用时,用rdb来进行快速的数据恢复

redis的事务

redis就是一个命令执行的队列,将一系列命令包装成一个队列,当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰

正常开发过程中运用的比较少,因为redis是单线程的

事务的基本操作

开启事务
multi
该命令表示事务的开启位置,此指令执行后,后续的所有指令均加入到事务(队列)中,并没有立即执行
执行事务
exec
该指令表示事务的结束位置,同时会执行事务,与multi成对使用,有一个multi就一定会有一个exec
取消事务
discard
当事务定义过程中出现问题可以使用该指令,终止当前事务的定义,发生在multi之后,exec之前,会破坏整个事务队列

事务锁

事务锁可以保证对同一个key不会重复操作,例如补货某宝上的某个货物,要保证不重复操作

添加事务锁
如果在执行exec前key发生了变化,那么终止事务操作
watch key1 key2 ...
取消对所有key的监视
unwatch
分布式锁
分布式锁可以保证最后一件商品不被多人同时购买,因此不仅要监控一个key,还要监控具体数据value
使用setnx设置一个公共锁
setnx lock-key value
如果公共锁不存在,那么设置成功,那么将会拥有控制权
如果已存在那么将设置失败,没有控制权,将排队等待
操作完毕后需要del来释放锁,避免死锁
为了避免拿到锁之后客户端宕机
改良分布式锁,给锁设置过期时间
expire lock-key second
pexpire lock-key milliseconds

redis的删除策略

所有数据都存放在内存中,但是我们可以通过TTL指令获取其中的状态
XX:具有时效性的数据
-1:永久有效的数据
-2:已经过期的数据或被删除的数据或未定义的数据

数据的删除策略

-定时删除

在设置键过期时间同时创建一个定时器,让定时器在键过期时立即对键进行删除

优点:节约内存

缺点:会占用CPU,影响响应时间和吞吐量

总结:用处理器性能换取存储空间,即拿时间换空间

-惰性删除

放任键过期,但是每次获取该键时都会检查这个键是否会过期,如果过期就删除这个键,如果没有过期就返回该键

优点:节约CPU性能,发现必须删除才删除

缺点:会占用内存,可能会发生内存泄漏

总结:用存储空间换取处理器性能,拿空间换时间

-定期删除

定期删除每隔一段时间执行一次删除过期键的操作,并通过限制删除操作执行的时长来减少删除操作对CPU的影响

该策略的难点在于确定删除操作执行的时长和频率

逐出算法(内存淘汰机制)

由于删除策略没有有效删除数据的话而导致内存爆满

那么将会清除一下存储空间,清理数据的策略称为逐出算法

注意
逐出算法并无法保证100%能清理出足够可使用的内存空间,如果不成功则反复执行

当对所有数据尝试完毕后,如果还不能达到内存清理的要求,那么将会报错

逐出算法的类型

  • noeviction: 不删除策略, 达到最大内存限制时, 如果需要更多内存, 直接返回错误信息

  • allkeys-lru: 所有key通用,优先删除最近最少使用(less recently used ,LRU) 的 key

  • allkeys-random: 所有key通用, 随机删除一部分 key

  • volatile-lru: 只限于设置了过期时间的数据, 优先删除最近最少使用的 key。

  • volatile-random: 只限于设置了过期时间的数据,随机删除一部分 key。

  • volatile-ttl: 只限于设置了过期时间的数据,优先删除剩余时间短的key

互联网“三高”架构

-高并发

-高性能

-高可用(集群)

集群的作用

-减轻单台服务器的访问压力,实现负载均衡

-分散单台服务器的存储压力,实现可扩展性

-降级单台服务器宕机带来的灾难

集群的结构设计

集群总的存储空间会被分为16384份,叫做哈希槽

每台主机会保存一部分,每份代表的是一个存储空间,而不是一个key的保存空间

当新加入机器时,那么会重新分16384份哈希槽,当有机器宕机时,更是如此

当存值时,每个key通过CRC16校验后对16384取模来决定放置哪个槽(Slot)

集群的内部通讯

集群中的每个节点在一定时间内会给其他节点发送ping消息,而其他节点会返回pong作为响应

因此所有节点可以得知集群内所有节点的槽信息

当get一个key时,redis将会计算得出key存储的槽位置,在根据槽位置找到对应的节点

如果槽在节点本身,那么将会直接返回key对应的数据

否则会返回重定向错误,并给客户端返回存储该槽的节点

因此get一个key时,最多需要两次

集群——主从模式

主从模式表示redis集群里会有一台服务器作为master,多台服务器作为slave

master跟slave上的数据保持一致,master负责处理写请求(也可以处理读请求,但一般不用),slave负责处理读请求

主从复制的作用

-数据备份

-扩展性能,可以读写分离

-高可用的基石,是构建哨兵模式和cluster集群的基础

主从复制的特征

-一个master可以有多个slaves,而一个slave只能有一个master

-master可以读写,slave只能读

-slave挂了不会影响其他服务器的读和写,重新启动后从master里自动同步数据

主从复制的工作流程

-建立连接阶段

建立slave和master的连接,使master能够识别slave,并保存slave端口号

-数据同步阶段(最核心阶段)

slave初次连接master后,复制master中的所有数据到slave,分为全量复制和部分复制

-命令传播阶段

master将新接收到的数据变更成命令发送到salve,salve接收命令后执行命令

数据同步阶段下的断联情形

-网络闪断闪联——忽略

-短时间内网络中断——部分复制

核心要素

1、服务器的运行id,即master运行时的id

2、master的复制缓冲区,存储master执行过的命令,是一个队列

3、主从服务器的复制偏移量

master的复制偏移量指的是发送给各个slave的同步数据的偏移量(记录数据同步的位置),有多少个slave就有多少个记录

slave的复制偏移量指的是master发送给slave同步数据的偏移量(接受数据的字节数)

-长时间网络中断——全量复制

命令传播阶段的心跳机制

进入命令传播阶段后,master与slave通过心跳机制来确保连接的有效性,来保证双方都在线

注意:当大多数slave掉线或延迟过高时,master为了保障数据稳定性,将拒绝所有信息同步操作

主从复制的完整流程

-建立连接阶段,master和slave建立连接

-数据同步阶段

1)如果主从节点的offset相等,那么将表明主从节点数据一致,直接进入到下一阶段

2)如果主从节点的offset不一致,且可以在复制缓冲区里找到缺少的那部分,那么将进行部分复制

3)如果主从节点的offset不一致,且不能在复制缓冲区中找到缺少的那部分,那么将进行全量复制

-命令传播阶段

通过心跳机制来保证双方都在线

如果master有新写入数据,那么master将接收到的数据变更命令发送到salve,salve接收命令后执行命令

集群——sentinel模式

哨兵模式是在主从模式的基础上进行的,多个哨兵(至少3个)组成一个分布式系统

用于对主从结构中的每台机器(master、slave、sentinel)进行监控

当出现故障时通过投票机制选择新的master并将所有slave连接到新的master

注意:

sentinel最好不要跟redis部署在同一台机器,不然redis挂了sentinel也会挂,通常哨兵配置数量为单数

哨兵的作用

主要完成主从切换的功能,主从切换包括以下阶段

-监控

每个sentinel每秒钟一次的频率向其他sentinel、master和slave发送ping命令,检查是否正常运行

-通知

如果master被监控到出现问题时,那么该sentinel会向其他sentinel服务器发送通知,此时是主观下线(即单台服务器认定master挂了)

当半数以上的哨兵认定master挂掉,那么将把master下线,此时叫做客观下线

然后哨兵们会选出一个哨兵leader(超过半数),由该哨兵leader决定哪一个slave来成为新的master,并进行故障转移操作

-自动故障转移

哨兵leader选取一个slave作为master,将其他的slave连接到master

哨兵leader选master的原则

-过滤点主观下线的节点

-选择优先级最大的节点

-如果没有则选择复制偏移量最大的节点

-如果还没有就选择运行时间长的,即runid最小的节点

cluster集群

哨兵模式下的每台服务器都存储相同的数据,很浪费内存,因此引入cluster模式,实现redis的分布式存储

也就是每台redis节点上存储不同的内容

实现原理:

redis主节点上存储两个东西,一个叫做槽(slot),一个是cluster;

槽的取值范围是0-16383,每个主节点都会存储一部分的槽

cluser就是一个管理集群的插件,当我们存取一个key时,redis会根据CRC16算法算出一个值,再让这个值去跟16384求与,这样就可以得到一个0-16383范围的值,通过这个值找到对应的节点,然后再去这个节点进行存取操作

cluster集群里的主从结构

一个主节点对应一个或者多个从节点,当主节点宕机时就会启动从节点

当其他节点ping主节点A时,如果半数以上的主节点与A通信超时,那么就可以认为主节点A宕机了

这时将启用从节点A1

如果从节点A1也宕机了,那么该集群就无法提供服务了

cluster的特点

-所有节点彼此互联(ping-pong机制)

-一个节点失效需要通过集群内半数以上的节点判定失效才失效

-客户端不需要和集群内所有机器连接,只需要和一个连接就可以

缓存预热

缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统,

避免用户请求的时,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据

缓存雪崩

短时间大量key集中过期,导致请求全部落到数据库,导致数据库短时间内承受大量请求而崩掉

解决方法:

-设置热点数据永不过期

-批量往redis存数据时,让每个key的失效时间都设置成随机值就可以,这样可以保证数据在同一时间内不会大面积失效

-加互斥锁,在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存

缓存击穿

某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,导致数据库短时间内承受大量请求而崩掉

解决方法:

-设置热点数据永不过期

-加互斥锁

缓存穿透

出现非正常的url访问,访问了redis和数据库不存在的数据,每次访问数据库,导致对数据库服务器造成压力

解决方法:

-增加参数校验,检查参数是否为空,是否符合要求

-缓存空值,当访问缓存和DB都没有查到值时,可以将空值写入缓存,但是要设置过期时间,该时间根据产品特性来设置

-使用布隆过滤器,使用布隆过滤器存储所有可能访问的key,不存在的key直接过滤,存在的key则进一步查询缓存和数据库

Redis集群至少需要3个master节点,所以现在总共有6个节点,就只能是1master对应1slave这种方式

所以:

1master-1slave,redis集群需要6个节点

1master-2slave,redis集群需要9个节点,以此类推

如何在一个亿级数据中判断某个元素是否存在

使用布隆过滤器,它是一个基于概率的数据结构,只能告诉我们一个元素绝对不在集合里,存在一定的误判率

首先创建一个位数组,数组里每个元素只有0和1两种状态,存在是1,不存在是0,初始状态全是0

通过哈希运算和位运算将一个找到一个值所对应的位置,然后把该位置的值设置成1

如果找到一个值的位置为0,那么那个元素一定不存在,如果为1,那么可能存在

题目:保证Redis 中的 20w 数据都是热点数据 说明是 被频繁访问的数据,并且要保证Redis的内存能够存放20w数据,要计算出Redis内存的大小

**题目:保留热点数据:对于保留 Redis 热点数据来说,我们可以使用 Redis 的内存淘汰策略来实现,可以使用allkeys-lru淘汰策略,**该淘汰策略是从 Redis 的数据中挑选最近最少使用的数据删除,这样频繁被访问的数据就可以保留下来了

保证 Redis 只存20w的数据:1个中文占2个字节,假如1条数据有100个中文,则1条数据占200字节,20w数据 乘以 200字节 等于 4000 字节(大概等于38M);所以要保证能存20w数据,Redis 需要38M的内存

题目:MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

限定 Redis 占用的内存,Redis 会根据自身数据淘汰策略,加载热数据到内存。所以,计算一下 20W 数据大约占用的内存,然后设置一下 Redis 内存限制即可

题目:假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?

使用 keys 指令可以扫出指定模式的 key 列表。对方接着追问:如果这个 Redis 正在给线上的业务提供服务,那使用 keys 指令会有什么问题?这个时候你要回答 Redis 关键的一个特性:Redis 的单线程的。keys 指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用 scan 指令,scan 指令可以无阻塞地提取出指定模式的 key 列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用 keys 指令长。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值