redis


在这里插入图片描述

什么是nosql(Not Only SQL)

关系型数据库:列+行,同一个表下数据的结构是一样的。
非关系型数据库:数据存储没有固定的格式,并且可以进行横向扩展。
NoSQL泛指非关系型数据库,随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区,暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的。

nosql特点

1.方便扩展(数据之间没有关系,很好扩展!)

2.大数据量高性能(Redis一秒可以写8万次,读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)

3.数据类型是多样型的!(不需要事先设计数据库,随取随用)
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

Redis 是什么

Redis(Remote Dictionary Server ),即远程字典服务。
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis能做什么

内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)
高效率、用于高速缓冲
发布订阅系统
地图信息分析
计时器、计数器(eg:浏览量)

行式数据库,列式数据库,图数据库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基础知识

redis默认有16个数据库
默认使用第一个
16个数据库为:DB 0~DB 15 默认使用DB 0 ,可以使用select n切换到DB n,dbsize可以查看当前数据库的大小,与key数量相关。
不同数据库键是不能互通的

keys * :查看当前数据库中所有的key。

flushdb:清空当前数据库中的键值对。

flushall:清空所有数据库的键值对。

Redis是单线程的,Redis是基于内存操作的。
所以Redis的性能瓶颈不是CPU,而是机器内存和网络带宽。???

Redis为什么单线程还这么快?
误区1:高性能的服务器一定是多线程的?
误区2:多线程(CPU上下文会切换!)一定比单线程效率高!
核心:Redis是将所有的数据放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个CPU上的,在内存存储数据情况下,单线程就是最佳的方案。?

在这里插入图片描述

Redis为什么快

  1. 纯内存操作,肯定快
    数据存储在内存中,读取的时候不需要进行磁盘的 IO

  2. 单线程,无锁竞争损耗
    单线程保证了系统没有线程的上下文切换
    使用单线程,可以避免不必要的上下文切换和竞争条件,没有多进程或多线程引起的切换和 CPU 的消耗,不必考虑各种锁的问题,没有锁释放或锁定操作,不会因死锁而降低性能;

  3. C 语言实现,更接近底层操作
    Redis 是用 C 语言开发完成的

  4. 多路 I/O 复用模型,非阻塞 IO
    采用多路 I/O 复用技术可以让单个线程高效的处理多个网络连接请求(尽量减少网络 IO 的时间消耗)
    非阻塞 IO 内部实现采用 epoll,采用了 epoll+自己实现的简单的事件框架。epoll 中的读、写、关闭、连接都转化成了事件,然后利用 epoll 的多路复用特性,绝不在 io 上浪费一点时间。

  5. 数据结构简单,底层又做了优化
    数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;

CAP

C:consistency,数据在多个副本中能保持一致的状态。

A:Availability,整个系统在任何时刻都能提供可用的服务,通常达到99.99%四个九可以称为高可用

P:Partition tolerance,分区容错性,在分布式中,由于网络的原因无法避免有时候出现数据不一致的情况,系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择,换句话说,系统可以跨网络分区线性的伸缩和扩展。

CAP理论的核心:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

CA:单点集群,满足一致性,可用性的系统,通常在可扩展上不太强大。应用:传统的Oracle数据库
CP:满足一致性,分区容错性的系统,通常性能不是特别高。应用:Redis,MongoDB,银行
AP:满足可用性,分区容错性,通常可能对一致性要求低一些。应用:大多数网站架构的选择
为什么?
BASE
基本可用(Basically Available)
软状态(Soft state)状态可以有一段时间不同步
最终一致(Eventually consistent)最终数据是一致的就可以了,而不是时时保持强一致

启动服务:
redis-server myredisconfig/redis.conf 这里开启的是最开始之前拷贝默认的配置文件redis.conf,安装好redis后,我们把他的配置文件拷贝了一份,并且进行了修改.我把它放在了/usr/local/bin
redis-server myredisconfig/redis.conf
redis-cli -p 6379

数据类型

Redis-Key
exists key:判断键是否存在
del key:删除键值对
move key db:将键值对移动到指定数据库
expire key second:设置键值对的过期时间
type key:查看value的数据类型
t关于TTL命令

Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:

当前key没有设置过期时间,所以会返回-1.
当前key有设置过期时间,而且key已经过期,所以会返回-2.
当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.

删除指令可以不用记,可以给key值附上有效期,有效期到了之后,该数据就会被删除了
String:
set/get/del/append(向后添加kv对)/strlen(字符串长度)

Incr(在当前数字进行+1操作)/decr(在当前数字进行-1操作)/incrby/decrby,一定要是数字才能进行加减

getrange/setrange(修改定位位置的值)

setex(set with expire)键秒值/setnx(set if not exist)
mset/mget/msetnx
getset(先get再set)
List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

LPUSH/RPUSH key value1[value2…]从左边/右边向列表中PUSH值(一个或者多个)。
LRANGE key start end 获取list 起止元素==(索引从左往右 递增)==
LPUSHX/RPUSHX key value 向已存在的列名中push值(一个或者多个)
LINSERT key BEFORE|AFTER pivot value 在指定列表元素的前/后 插入value
LLEN key 查看列表长度
LINDEX key index 通过索引获取列表元素
LSET key index value 通过索引为元素设值
LPOP/RPOP key 从最左边/最右边移除值 并返回
RPOPLPUSH source destination 将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部
LTRIM key start end 通过下标截取指定范围内的列表
LREM key count value List中是允许value重复的 count > 0:从头部开始搜索 然后删除指定的value 至多删除count个 count < 0:从尾部开始搜索… count = 0:删除列表中所有的指定value。
BLPOP/BRPOP key1[key2] timout 移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOPLPUSH source destination timeout 和RPOPLPUSH功能相同,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
set
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

SADD key member1[member2…] 向集合中无序增加一个/多个成员
SCARD key 获取集合的成员数
SMEMBERS key 返回集合中所有的成员
SISMEMBER key member 查询member元素是否是集合的成员,结果是无序的
SRANDMEMBER key [count] 随机返回集合中count个成员,count缺省值为1
SPOP key [count] 随机移除并返回集合中count个成员,count缺省值为1
SMOVE source destination member 将source集合的成员member移动到destination集合
SREM key member1[member2…] 移除集合中一个/多个成员
SDIFF key1[key2…] 返回所有集合的差集 key1- key2 - …
SDIFFSTORE destination key1[key2…] 在SDIFF的基础上,将结果保存到集合中==(覆盖)==。不能保存到其他类型key噢!
SINTER key1 [key2…] 返回所有集合的交集
SINTERSTORE destination key1[key2…] 在SINTER的基础上,存储结果到集合中。覆盖
SUNION key1 [key2…] 返回所有集合的并集
SUNIONSTORE destination key1 [key2…] 在SUNION的基础上,存储结果到及和张。覆盖
SSCAN KEY [MATCH pattern] [COUNT count] 在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分
hash:
hset/hget/hmset/hmget/hgetall/hdel
hset和hmset的区别就在于hmset可以同时赋多值(现在改版都可以了)
hlen
hexists key 在key里面的某个值的key
hkeys/hvals
hincrby/hincrbyfloat
hsetnx
lrange list01 0 -1 这个意思是全取,而在set中他用smembers set01 来查看全部
**hash:**kv模式不变,但是V它又是一个键值对
zset
还有三种特殊的数据类型
Geospatial(地理位置),Hyperloglog(基数统计)BitMaps(位图)

应用场景

在这里插入图片描述

String

计数器

hash

对象缓存(key:属性 value:值)
购物车(key:商品名 value:价格)

list

在这里插入图片描述
常见的数据结构:栈,队列,阻塞队列
微博,微信公众号消息流,后发的在上面

set (集合)

抽奖
点赞
朋友之间的关注模型(陌陌,微博等等)(交集)

zset(有序集合)

排行榜

事务

在这里插入图片描述
Redis的单条命令是保证原子性的,但是redis事务不能保证原子性
Redis事务操作过程
开启事务(multi)
命令入队
执行事务(exec)
在事务开始后,执行之前,之间入过有编译错误的话(打错单词也算),所有的命令都会失效,但是如果是运行时异常的话只有运行异常的那条命令失效,如incr命令,他在int数值类型上进行增加,但如果给一个value为string类型的数据进行增加的时候,他没有执行时是无法识别的,只有最后exec后才能发现,最后没有执行的就只有incr这一条命令。 所以不保证事务原子性
DISCARD放弃事务,之前的正在事务中的命令都不执行了

监控

悲观锁:很悲观,认为什么时候都会出现问题,无论做什么都会加锁
乐观锁:很乐观,认为什么时候都不会出现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据
获取version
更新的时候比较version
使用watch key监控指定数据,相当于乐观锁加锁
锁一般配合着事务进行操作:
正茬执行
在这里插入图片描述
执行失败
在这里插入图片描述
在这里插入图片描述
UNwatch,取消监控
如果已经执行了exec或者discard命令后,就没有必要在进行unwatch操作了

Jedis

持久化

持久化方式:
RDB(默认)
AOF
默认开启

#如果900s内,如果至少有一个1 key进行了修改,我们及进行持久化操作
save 900 1
#如果300s内,如果至少10 key进行了修改,我们及进行持久化操作
save 300 10
#如果60s内,如果至少10000 key进行了修改,我们及进行持久化操作
save 60 10000

因为Redis持久化选择RDB快照模式,所以Redis并不是实时的进行数据持久化,而是有一定的时间间隔。这个时候如果我们想要手动进行一次持久化,可以使用save或者bgsave命令。
bgsave会在后台异步进行快照操作,快照同时还可以响应客户端请求
save时只管保存,奇特不管,全部阻塞,手动保存(不建议使用)
什么是RDB(Redis DataBase)
在这里插入图片描述
key的值改变的越多,就会在越短的时间内进行持久化。
在指定时间间隔后,将内存中的数据集快照写入数据库 ;在恢复时候,直接读取快照文件,进行数据的恢复 ;
默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。文件名可以在配置文件中进行自定义。
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。临时文件的存在是因为:如果直接在rdb文件中写,而此时Redis损坏了,此时rdb的写也就停止了,rdb文件没有写完,造成了rdb文件的损坏。这就是“写时复制技术”
这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。我们默认的就是RDB,一般情况下不需要修改这个配置! 有时候在生产环境我们会将这个文件进行备份!
rdb保存的文件是dump.rdb 都是在我们的配置文件中快照中进行配置的!

在进行 RDB 的时候,redis 的主线程是不会做 io 操作的,主线程会 fork 一个子线程来完成该操作;

Redis 调用forks。同时拥有父进程和子进程。
子进程将数据集写入到一个临时 RDB 文件中。
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益(因为是使用子进程进行写操作,而父进程依然可以接收来自客户端的请求。)

触发机制
save的规则满足的情况下,会自动触发rdb原则
执行flushall命令,也会触发我们的rdb原则
退出redis,也会自动产生rdb文件
bgsave?
bgsave 是异步进行,进行持久化的时候,redis 还可以将继续响应客户端请求
在这里插入图片描述
在这里插入图片描述
如果恢复rdb文件:
1、只需要将rdb文件放在我们redis启动目录就可以,redis启动的时候会自动检查dump.rdb 恢复其中的数据!
2、查看需要存在的位置

127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" # 如果在这个目录下存在 dump.rdb 文件,启动就会自动恢复其中的数据

优缺点
优点:

适合大规模的数据恢复
对数据的完整性要求不高
缺点:

需要一定的时间间隔进行操作,如果redis意外宕机了,这个最后一次修改的数据就没有了。
fork进程的时候,会占用一定的内容空间。

AOF:(Append Only File)
将我们所有写的命令都记录下来,history,恢复的时候就把这个文件全部再执行一遍
在这里插入图片描述

以日志的形式来记录每个写的操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

什么是AOF
​ 快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、以及未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。

appendonly no yes则表示启用AOF
默认是不开启的,我们需要手动配置,然后重启redis,就可以生效了!
如果这个aof文件有错位,这时候redis是启动不起来的,我需要修改这个aof文件。
redis给我们提供了一个工具redis-check-aof --fix
当aof和rdb同时开启时,aof生效,rdb不会

Rewrite压缩:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

优缺点
优点
每一次修改都会同步,文件的完整性会更加好
没秒同步一次,可能会丢失一秒的数据
从不同步,效率最高
缺点
相对于数据文件来说,相同的数据,aof远远大于rdb,修复速度比rdb慢!
Aof运行效率也要比rdb慢,所以我们redis默认的配置就是rdb持久化

扩展:
1、RDB 持久化方式能够在指定的时间间隔内对你的数据进行快照存储
2、AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以Redis 协议追加保存每次写的操作到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
3、只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化
4、同时开启两种持久化方式

在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
RDB 的数据不实时,同时使用两者时服务器重启也只会找AOF文件,那要不要只使用AOF呢?作者建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的Bug,留着作为一个万一的手段。
5、性能建议

因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留 save 900 1 这条规则。
如果Enable AOF ,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了,代价一是带来了持续的IO,二是AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小重写可以改到适当的数值。
如果不Enable AOF ,仅靠 Master-Slave Repllcation 实现高可用性也可以,能省掉一大笔IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave 同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个 Master/Slave 中的 RDB文件,载入较新的那个,微博就是这种架构。
在这里插入图片描述
RDB持久化方法能够在指定的时间间隔对你的数据进行快照存储
AOF以追加保存每次写的操作到文件末尾

Redis发布订阅

edis是使用C实现的,通过分析 Redis 源码里的 pubsub.c 文件,了解发布和订阅机制的底层实现,籍此加深对 Redis 的理解。

Redis 通过 PUBLISH 、SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能。

每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构, 结构的 pubsub_channels 属性是一个字典, 这个字典就用于保存订阅频道的信息,其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。
缺点
如果一个客户端订阅了频道,但自己读取消息的速度却不够快的话,那么不断积压的消息会使redis输出缓冲区的体积变得越来越大,这可能使得redis本身的速度变慢,甚至直接崩溃。
这和数据传输可靠性有关,如果在订阅方断线,那么他将会丢失所有在短线期间发布者发布的消息。
应用
消息订阅:公众号订阅,微博关注等等(起始更多是使用消息队列来进行实现)
多人在线聊天室。
稍微复杂的场景,我们就会使用消息中间件MQ处理。

Redis主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。

默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。
作用
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础。
为什么使用集群
一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的(宕机),原因如下:

1、从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;

2、从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台Redis最大使用内存不应该超过20G。

电商网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是"多读少写"。

对于这种场景,我们可以使如下这种架构:
在这里插入图片描述

注意注意!!! 如果redis配置了requirepass,配置主从复制的时候会失败!一定要设置masterauth;或者注销掉密码!!
默认情况下,每台Redis服务器都是主节点,所以只配置slave不用配置master
修改对应的信息
端口
pid名字
log文件名
dump.rdb名字
在这里插入图片描述

真实的从主配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,暂时的!
1.当主机断电宕机后,默认情况下从机的角色不会发生变化 ,集群中只是失去了写操作,当主机恢复以后,又会连接上从机恢复原状。当使用哨兵后,宕机又连上去之后就不会恢复原状了

2.当从机断电宕机后,若不是使用配置文件配置的从机,再次启动后作为主机是无法获取之前主机的数据的,若此时重新配置称为从机,又可以获取到主机的所有数据。这里就要提到一个同步原理。

3.第1条中提到,默认情况下,主机故障后,不会出现新的主机,有两种方式可以产生新的主机:
1.从机手动执行命令slaveof no one,这样执行以后从机会独立出来成为一个主机
2.使用哨兵模式(自动选举)

哨兵模式

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
在这里插入图片描述
哨兵的作用:

通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
在这里插入图片描述
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
配置哨兵配置文件 sentinel.conf
sentinel monitor myredis 127.0.0.1 6379 1
后面的这个数字1代表如果主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机

哨兵模式优缺点
优点:
哨兵集群,基于主从复制模式,所有主从复制的优点,它都有
主从可以切换,故障可以转移,系统的可用性更好
哨兵模式是主从模式的升级,手动到自动,更加健壮 缺点:
Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
实现哨兵模式的配置其实是很麻烦的,里面有很多配置项

缓存穿透,缓存击穿,缓存雪崩

缓存穿透是击穿了两层,数据库和redis都没有数据
而击穿是击穿了一层,redis没有数据,数据库有数据

缓存穿透:

访问一个缓存和数据库都不存在的 key,此时会直接打到数据库上,并且查不到数据,没法写缓存,所以下一次同样会打到数据库上。或者是很多非正常的url访问
解决方案:
1、接口校验。在正常业务流程中可能会存在少量访问不存在 key 的情况,但是一般不会出现大量的情况,所以这种场景最大的可能性是遭受了非法攻击。可以在最外层先做一层校验:用户鉴权、数据合法性校验等,例如商品查询中,商品的ID是正整数,则可以直接对非正整数直接过滤等等。

2、缓存空值。当访问缓存和DB都没有查询到值时,可以将空值写进缓存,但是设置较短的过期时间,该时间需要根据产品业务特性来设置。

3、布隆过滤器。使用布隆过滤器存储所有可能访问的 key,不存在的 key 直接被过滤,存在的 key 则再进一步查询缓存和数据库。
布隆过滤器:
布隆过滤器的特点是判断不存在的,则一定不存在;判断存在的,大概率存在,但也有小概率不存在。并且这个概率是可控的,我们可以让这个概率变小或者变高,取决于用户本身的需求。

布隆过滤器由一个 bitMaps 和 一组 Hash 函数(算法)组成,是一种空间效率极高的概率型算法和数据结构,主要用来判断一个元素是否在集合中存在。
在这里插入图片描述

在初始化时,bitSet 的每一位被初始化为0,同时会定义 Hash 函数,例如有3组 Hash 函数:hash1、hash2、hash3。
当某个数(查询)据经过hash函数就按过后,得到了三个地址,此时这三个地址都会由0变为1,原本就是1的就不用再变了,但就是因为有的已经是1了,他是其他数据经过hash计算得来的,此时会判断的不太准确,当某个数据的三个hash值都已经有了数值1,所以有的数据就不一定准确。
布隆过滤器的特点是判断不存在的(bit值为0),则一定不存在;判断存在的,大概率存在,但也有小概率不存在。
解决方案:
1.一个是加大 bitMaps 的长度,这样不同的值出现“冲突”的概率就降低了,从而误判率也降低。
2.提升 Hash 函数的个数,Hash 函数越多,每个值对应的 bit 越多,从而误判率也降低。

布隆过滤器和hashMap

当数据量不大时,HashMap 实现起来一点问题都没有,而且还没有误判率,简直完美.
当数据量上去后,布隆过滤器的空间优势就会开始体现,特别是要存储的 key 占用空间越大,布隆过滤器的优势越明显。
布隆过滤器占用多少空间,主要取决于 Hash 函数的个数,跟 key 本身的大小无关,这使得其在空间的优势非常大。

缓存击穿

某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。

解决方案:
加互斥锁。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。
业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

预先设置热门数据:在高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长
实时监控:现场监控那些数据热门,适时调整key的过期时长

缓存雪崩

大量的热点 key 设置了相同的过期时间,导在缓存在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩,甚至导致数据库被打挂。缓存雪崩其实有点像“升级版的缓存击穿”,缓存击穿是一个热点 key,缓存雪崩是一组热点 key。

解决方案:
1、过期时间打散。既然是大量缓存集中失效,那最容易想到就是让他们不集中生效。可以给缓存的过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效。

2、热点数据不过期。该方式和缓存击穿一样,也是要着重考虑刷新的时间间隔和数据异常如何处理的情况。

3、加互斥锁。该方式和缓存击穿一样,按 key 维度加锁,对于同一个 key,只允许一个线程去计算,其他线程原地阻塞等待第一个线程的计算结果,然后直接走缓存即可。

实现session共享

当使用集群(分布式)架构
在这里插入图片描述
session该如何存储
第一次操作访问了服务器1,服务器1中产生了session对象,第二次访问就访问到了服务器2,服务器2中没有session对象,所以就要输入账号密码了
所以session该如何存储:
1.存放到cookie中(不建议,不安全)
2.session复制,将服务器中有的session复制到 其他服务其中(浪费内存,不建议)
3.引出一个nosql数据库,可以把用户信息存储到nosql中。

Redis插槽

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值