[指北]为什么选择 redis

Redis C语言开发深入底层,数据放在内存中,网络层使用epoll解决高并发问题

另外,除了做缓存之外,Redis 也经常用来做分布式锁,甚至是消息队列。

Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。

采用单线程: 非阻塞的异步事件处理,IO时间不会很长也能够避免线程上下文切换。(多线程处理网络IO读取和写入,核心IO负责串行处理客户端指令)

redis 为什么快

1.基于内存
2.简单的底层数据结构
3.单线程,减少上下文切换
4.网络模型为io多路复用

为什么选择redis

  1. redis支持复杂的数据结构,哈希,列表,集合,有序集合等,me只支持String
  2. redis的持久化功能
    ○ 缓存场景: redis挂了重启后能够快速恢复热数据,不会瞬时将压力压到数据库上
    ○ redis挂了的过程中,如果数据库中有修改,可能会导致redis重启后与数据库数据不一致
  3. 高可用
    redis天然支持集群,可实现主动复制,读写分离,官方还提供了sentinel集群管理工具。
    memcache 实现高可用需要二次开发
  4. 存储内容超过1M
    mecache的value最大只能存储1M (压缩或分割)

缺点:

  1. redis是临时申请空间,可能会有碎片
  2. redis单线程,me多线程,使用cas保证数据一致性。

数据类型

  1. String
    最大:512M
    编码方式:raw、int、embstr
    不超过long类型的整数值 保存为 int 底层为 long
    长度大于39字节的字符串 保存为 raw 底层为 sds
    长度小于 39 字节的字符串 保存为 embstr 底层为 sds
    sds (simple Dynamic String)简单动态字符串,类似arraylist,可通过预分配冗余空间减少内存的频繁分配
    简单的key-value类型,value不仅可以是string,也可以是数字
    String能够进行扩容,会有一定的free空间,如果删除部分字段的时候空闲时间不会立即删除而是留给下一次操作,如果下一次操作还是没有操作free空间,才会删除回收。而且是按照长度来寻找字符串。

  2. Hash
    键值对个数:2^32-1
    ziplist、HashTable
    所有键值对的键和值的字符串长度都小于 64 字节并且保存的键值对数量小于 512 个 用 ziplist
    内部包含两个hashtable,但是只有一个是有值的,在扩缩容时需要分配新的HashTable进行渐进式rehash
    渐进式hash: 在rehash的同时保留两个hash结构,查询会同时查询两个hash结构,循序渐进将旧结构迁移到新字典,搬迁完成时会用新的结构取代
    是string类型的field和value的映射表,hash比较适合用于存储对象,后续操作的时候可以仅修改这个对象中的某个字段的值,比如用户信息商品信息等

  3. List
    元素个数最多为:2^32-1个
    ziplist , LinkedList双端链表
    列表对象保存的所有字符串元素的长度都小于64字节,且元素个数小于512个时 使用 ziplist (为节约内存,会使用连续的内存块)
    双向链表,可以支持反向查找和遍历操作方便,但是会有部分额外开销
    lrange 命令可以基于list实现分页查询,高性能分页

  4. set
    元素个数最多为:2^32-1个
    intset , Hashtable
    元素都是整数,并且个数不超过512个时,使用 intset
    是一种无序集合,提供了判断某个成员是否在一个set集合内的重要接口,可以基于set实现交集、并集、差集的操作

  5. Sorted Set (Zset)
    Skiplist (跳跃链表) ,ziplist
    有序集合保存的元素个数小于 128 个,且所有元素成员长度都小于 64 字节时,使用 ziplist
    增加了权重参数score,是集合中的元素能按照score有序排列
    SkipList:相邻的节点之间也增加指针 ,插入时节点的层数是随机的,插入节点只需要修改节点前后的指针,不需要对多个节点进行调整,降低了插入的复杂度,最大层数64层,能存放2^64 个元素。

  6. Bitmap
    支持按bit位存储信息,用来实现布隆过滤器

  7. HyperLogLog
    不精确的去重计数功能

  8. Geospatial
    保存地理位置

  9. pub/sub
    订阅发布功能,可以做最简单的消息队列,如果消费者下线,消息会丢失

  10. Pipeline
    可以批量执行一组指令,一次性返回全部结果,影响qps峰值的是pipeline批次指令的数目。

  11. Lua 脚本
    可以保证多个指令的原子性执行

布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

过期时间

redis会设置过期时间,判断过期是定期删除+惰性删除

● 定期删除
○ 默认每隔100ms随机抽取一些设置了过期时间的key,检查是否过期,如果过期就删除
● 惰性删除
○ 定期删除会导致很多过期key到了时间还没有被删除,系统去查询过期key的时候会被删除掉。

这样还会有过期key存在内存中,导致redis内存块耗尽所以有了内存淘汰机制

内存淘汰机制

mysql中有2000w数据,redis中有20w怎么保证redis中的数据都是热点数据

Redis 提供 6 种数据淘汰策略:

  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  4. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  6. no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!

4.0 版本后增加以下两种:

  1. volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
  2. allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key

持久化

RDB和AOF

RDB 单独fork一个进程做持久化,所以对redis的性能影响比较小,数据恢复的比较快,但是如果文件较大也会导致客户端暂停几毫秒甚至几秒

快照文件,可能五分钟或者更长时间才会备份一次,可能会导致数据丢失

AOF 日志追加的形式,每秒进行一次,但是文件较大,达到一定程度可以进行重写压缩指令

RDB做冷备,AOF做热备

集群

  1. 主从
    读写分离
    不能容错恢复,一旦宕机可能导致数据不一致,容量受限于单机
  2. 哨兵模式
    哨兵的作用:
    a. 监控master和slave是否正常运行
    b. 多个哨兵之间能互相监控
    c. 如果master宕机能够选举slave成为master
  3. 集群
    无中心结构,每个结点有插槽,0-16383,每个key能够找到对应的哈希槽,从而去找到对应的节点,然后在这个节点上进行存取操作。
    为保证高可用,引入主从复制,每个节点有一个从机,如果超过半数与某节点连接超时则认为宕机,切换从机,如果从机也宕机,那么集群无法提供服务。
    最小配置为6台(三主三从)

一般会用主从+哨兵模式(三台)

缓存问题

  1. 击穿
    某个热点key失效时,恰好有大量并发请求,造成DB压力过大而崩溃
    解决方法:
    可以将热点数据设置为永不过期,需要考虑实际情况
    使用互斥锁,mutex key
    通过 synchronized + 双重检查机制:某个key只让一个线程查询,阻塞其他线程
  2. 穿透
    查询一个数据库一定不存在的数据,这样不会进行缓存,对数据库造成压力(一般为恶意攻击)
    解决方式:
    a. 如果从数据库中没查到数据时就写一个空值到缓存中,设置过期时间,这样在缓存失效前都可以从缓存中拿取数据
    b. 如果方法1中有大量的恶意请求就会导致redis中有大量的无效缓存所以有布隆过滤器
    通过它可以判断一个给定数据是否存在于海量数据中,进需要判断key是否合法。把所有可能存在的请求的值放到布隆过滤器中,用户发请求会判断值是否存在,不存在直接返回,存在则继续查询
  3. 雪崩
    多个key查询并且出现高并发,缓存中失效或查不到,都去DB查询,导致DB压力过大崩溃
    解决办法:
    Redis服务不可用:
    a. 采用Redis集群,避免单机出现问题整个缓存服务都没办法使用。
    b. 限流,避免同时处理大量的请求。
    热点缓存失效:
    a. 设置不同的失效时间比如随机设置缓存的失效时间。
    b. 缓存永不失效。
  • 32
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荼白z

感谢老板请我喝咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值