Redis

Redis

一、Redis 的应用场景

缓存、消息中间件(队列,发布-订阅)、分布式锁、服务注册中心、web集群Session共享、阅读量。

二、Redis 的数据类型和使用场景

2.1 String

2.2 hash

这里 value 值存的是结构化的对象,比较方便的就是操作其中的某个字段。这种数据结构存储用户信息,以 CookieID 作为 key ,设置 30 分钟为缓存过期时间,能很好的模拟出类似 Session 的效果。

2.3 list

List 的数据结构,具有先进先出的原则,可以做简单的消息队列的功能,可以利用 lrange 命令,做基于 Redis 的分页功能。

2.4 set

Set 堆放的是一堆不重复的数据集合,做全局去重的功能。利用交集、并集、差集等操作,可以计算共同喜好、全部喜好独有的喜好等等。

2.5 zset(sorted set)

sorted set 多了一个权重参数 score ,集合中的元素能够按 score 进行排列。可以做排行榜应用,取 TOP N 操作。

三、Redis 的持久化机制

Redis 是一个支持持久化内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。

3.1 RDB

Redis 默认的持久化方式是 RDB,通过持久化机制把内存中的数据以快照的形式保存到硬盘上对应产生的数据文件为 dump.rdb,通过配置文件中的 save 参数来定义快照的周期。

save9001900s内,如果有1个key被修改,则发起快照保存
save30010300s内,如果有10个key被修改,则发起快照保存
save601000060s内,如果有10000个key被修改,则发起快照保存

3.2 AOF

配置文件中 appendonly 修改为 yes,开启 AOF 持久化。开启后,启动 redis 服务端,发现多了一个 appendonly.aof 文件,新命令会被追加到文件的末尾。实际上,AOF持久化并不会立即将命令写入到硬盘文件中,而是写入到硬盘缓存,在接下来的策略中,配置多久来从硬盘缓存写入到硬盘文件。

appendfsyncaways每次操作都会立即写入aof文件中
appendfsynceverysec每秒持久化一次(默认配置)
appendfsyncno不主动进行同步操作,默认30s一次

四、单线程的 Redis 为什么这么快

  1. 纯内存操作
  2. 单线程操作
  3. 采用了 I/O 多路复用机制

五、Redis 的过期策略和内存淘汰机制

5.1 过期策略

Redis 采用的是定期删除+惰性删除策略

**定时删除:**给 key 设置一个过期时间,一旦键过期就会立即被删除,并释放所占用的内存,但对 cpu 不友好,当一批 key 过期时,正好遇上 cpu 紧张的阶段,这时候需要的是 cpu 处理能力,而不是内存,cpu 时间过多用在了删除过期 key 上,肯定会对服务器的响应时间和吞吐量造成影响。

**定期删除:**Redis 默认每隔 100ms 检查,是否有过期的key,有过期key则删除。需要说明的是,Redis 每隔 100ms,随机抽取检查(若是全部检查,则需要遍历,若存在大量数据,会非常影响性能的)是否有过期的 key,有过期 key 则删除。如果只采用定期删除策略,会导致很多 key 到时间没有删除。于是,惰性删除派上用场。

**惰性删除:**也就是说在你获取某个 key 的时候,Redis会检查一下,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除。如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。惰性删除依赖过期键的被动访问,对于内存很不友好,如果一些键长期没有被访问,会造成内存泄漏(垃圾数据占用内存)。

5.2 内存淘汰机制

由于过期策略存在的问题,就需要其它的策略去弥补它的不足,所以就有了内存淘汰机制。Redis 配置文件中可以设置 maxmemory-policy:内存的最大使用量,到达限度时会执行内存淘汰机制。没有配置时,默认为no-eviction。

在 redis.conf 配置文件中,有这样的描述:

//该配置就是配内存淘汰策略的,默认是:no-eviction
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
# 
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
# 
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction       
名称描述
volatile-lru已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-lfu已设置过期时间的数据集中挑选最不经常使用的数据淘汰
volatile-ttl已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random已设置过期时间的数据集中挑选任意数据淘汰
allkeys-lru当内存不足写入新数据时淘汰最近最少使用的Key
allkeys-random当内存不足写入新数据时随机选择key淘汰
allkeys-lfu当内存不足写入新数据时移除最不经常使用的Key
no-eviction当内存不足写入新数据时,写入操作会报错,同时不删除数据

六、Memcache 与 Redis 的区别

区别MemcacheRedis
存储方式Memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小Redis 有部份存在硬盘上,当物理内存用完时,Redis可以将一些很久没用到的 value 交换到磁盘。并且 Redis 可以持久化其数据。
数据类型Memcached 所有的值均是简单的字符串支持更为丰富的数据类型:String、hash、list、set、zset
性能Memcached 可以使用多核,平均每一核上,存储小数据 Redis 性能更高,在 100k 以上的数据存储,Memcached 性能更高Redis 只是用单核,比 Memcached 的存储性能低
value值1M512M

七、缓存雪崩、缓存击穿、缓存穿透

7.1 缓存雪崩

**是指在某一个时间段,缓存集中过期失效,大量的请求落到数据库上,DB瞬时压力过重。**比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩。

  1. 进行服务限流,从而避免key失效时一下子有大量的请求落到数据库上。
  2. 设置key的时候,加上一个随机因子。这样能尽可能分散缓存过期时间
  3. 热点key缓存时间稍微长一些,冷门key稍微短一点。

7.2 缓存击穿

缓存击穿,是指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个 key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

解决:热点 key 设置为永不过期,可在数据库数据加上一个字段,比如叫热点次数,每请求一次,值加一,一旦超过规定的值,动态的存入 Redis 中,设置为永不过期,或者根据这个值,动态的调整过期时间。

7.3 缓存穿透

查询一个数据库本不存在的数据,正常的业务逻辑是,先查询缓存,不存在查询数据库,相当于进行了两次无用的查询。如果传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象。**就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。**假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。即便是采用UUID,也是很容易找到一个不存在的KEY,进行攻击。

  1. 采用缓存空值的方式:如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。

  2. 布隆过滤器: 提前将全部数据的 key 哈希到一个足够大的 bitmap 中,查询一个不存在的 key 值,经过布隆过滤器拦截掉就不会去请求数据库了,布隆过滤器缺点是可能存在误判。一定可以判定不存在,但不能判定一定存在。因为布隆过滤器存储的是不完整的数据,相比 hashMap 可以占用更小的内存,大数据量的情况可以使用布隆过滤器做缓存穿透。

八、Redis 集群

8.1 主从复制

最低配置一主二从,主节点只负责写操作,从节点只能读操作。

树状集群

伪集群搭建,再复制两份配置文件,分别修改端口号、pid、dunp.rdb、log。分别启动三个节点。在从节点可以使用命令:SLAVEOF 127.0.0.1 6379 指定主节点,或在配置文件修改。

这种集群存在的问题就是,当主节点宕机后,还没来得及同步给从节点,就会造成数据丢失。

8.2 Sentinel 模式(哨兵)

当服务节点挂掉以后,都需要手动指定主节点,非常麻烦,所以产生了哨兵模式。

哨兵模式

其原理是哨兵向Redis服务器发送命令。等待Redis服务器响应,从而监控运行多个Redis服务实例。实际工作中哨兵也是配置集群模式。

哨兵集群

集群中的某个哨兵监测到主服务节点不能使用时,并不会立刻进行故障转移,只要哨兵集群中过半数的哨兵监测到主服务节点挂掉时,那么哨兵间进行一次投票,投票的结果由一个哨兵发起,进行故障转移,切换新的主服务节点成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值