redis

快速入门

NOSQL

在这里插入图片描述

介绍

在这里插入图片描述

常见命令

通用

在这里插入图片描述

java客户端:SpringDataRedis

RedisTemplate

  • 默认接收Object作为值写入Redis,写入前会把Object序列化为字节形式,默认是采用JDK序列化。
  • 缺点:可读性差、内存占用较大。

自定义序列化方式

  • 方法
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = 
            							new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}
  • 缺点:存入redis时会自动记录class名称,会额外带来内存开销。
    在这里插入图片描述

StringRedisTemplate(推荐)

  • key和value的序列化方式默认是String方式。
  • 缺点:写入对象时,需要手动序列化成json;读取对象时,需要把json反序列化为对象。

消息队列

List消息队列

在这里插入图片描述

PubSub消息队列

在这里插入图片描述

Stream消息队列

在这里插入图片描述

Stream消费者组消息队列

在这里插入图片描述

对比

在这里插入图片描述

分布式缓存

持久化

  • hm文档

RDB

  • 在redis停机时会触发一次。
  • 在配置文件中配置保存策略(多少秒内有多少个key被修改就保存一次)。
  • 原理:复制一份新的RDB文件把内存中的数据写入新文件,然后新文件替换老文件。

AOF(Append Only File追加文件)

  • 原理:每一个写的命令都会记录在AOF文件。
  • 缺点:AOF文件会比RDB文件大的多。
  • 可在配置文件中配置根据文件数量、大小触发重写AOF文件(去掉重复的命令,只保留最后一条)的机制。

对比

在这里插入图片描述

  • 优点:RDB启动时速度比较快;AOF数据安全性比较高。
  • 缺点:RDB在写入数据时宕机有数据丢失的风险;AOF文件比较大。

主从同步

  • 主从同步当全量同步时是主节点发送RDB文件给从节点。
  • 增量同步时是主节点发送日志文件给从节点。

哨兵

作用
  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作。
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主。
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端。

优点

  • 提高并发能力。
  • 高可用。

缺点

  • 海量数据存储、高并发写时性能不好。

分片集群

特征

  • 集群中有多个master,每个master保存不同数据。
  • 每个master都可以有多个slave节点。
  • master之间通过ping监测彼此健康状态。
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点。

插槽

原理
  • Redis会把每一个master节点映射到(0~16383共16384个)插槽上。
  • 数据的key与插槽绑定,根据key的有效部分计算插槽值。
    1.key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分。
    2.key中不包含“{}”,整个key都是有效部分。
判断某个key应该在哪个实例
  • 根据key的有效部分计算哈希值,对16384取余。
  • 余数作为插槽,寻找插槽所在实例即可。
将同一类数据固定的保存在同一个Redis实例
  • 这一类数据使用相同的有效部分,例如key都以{typeId}为前缀。

集群伸缩

  • 节点增删。

故障转移

  • 集群中的master宕机,slave会自动成为主节点。

多级缓存

在这里插入图片描述

JVM缓存

  • Caffeine
  • https://github.com/ben-manes/caffeine

Nginx缓存

  • 场景:频繁查询,数据很少会变化。
  • lua
  • OpenResty
    1.基于 Nginx的高性能 Web 平台。
    2.具备Nginx的完整功能。
    3.基于Lua语言进行扩展,集成了大量精良的 Lua 库、第三方模块。
    4.允许使用Lua自定义业务逻辑自定义库
    5.官方网站: https://openresty.org/cn/

redis缓存预热

  • InitializingBean

缓存同步

  • canal

最佳实践

key设计

  • 基本格式:[业务名称]:[业务描述]:[key名称]
  • 长度不超过44字节( key是string类型,底层编码包含int、embstr和raw三种。embstr在小于44字节使用,采用连续内存空间,内存占用更小。当字节数大于44字节时,会转为raw模式存储,在raw模式下,内存空间不是连续的,而是采用一个指针指向了另外一段内存空间,在这段空间里存储SDS内容,这样空间不连续,访问的时候性能也就会收到影响,还有可能产生内存碎片)。
  • 不包含特殊字符。

拒绝bigkey

推荐值

  • 单个key的value小于10KB。
  • 对于集合类型的key,建议元素数量小于1000。

bigkey危害

在这里插入图片描述

如何发现bigkey

如何删除bigkey

数据类型选用

string

  • 结构底层没有太多内存优化,每个key都有很多修饰的元数据。
  • 适合短小的数据。

hash

  • 底层使用ziplist,空间占用小;每个字段都是独立存储的,可以针对单个字段做CRUD。
  • hash的key、value数量超过500时,会使用哈希表而不是ZipList,内存占用较多。解决方案:
    1.拆分为小的hash。
    2.可以通过设置redis的hash-max-ziplist-entries配置entry上限。但是如果entry过多也会就会导致BigKey问题。
  • 配置信息、保存一个对象后续对象属性的进行修改(员工信息、部门信息、商品信息)。
    在这里插入图片描述

list

  • 集合数据,经常不断的存取。
  • 物流轨迹、岗位。

set

  • 没有重复值的集合数据,存入的值要是唯一的。
  • 投票的人、报修的设备。

sortedset

  • 可排序的set集合。
  • 里面的每一个元素都带有一个score属性,可以基于score属性对元素排序。

批处理优化

    • 尽量使用批处理,减少网络传输次数,进而减少网络传输耗时。

Pipeline

  • MSET虽然可以批处理,但是却只能操作部分数据类型,因此如果有对复杂数据类型的批处理需要,建议使用Pipeline。

集群下批处理

  • 批处理命令的多个key必须落在一个插槽中,否则就会导致执行失败。
  • spring-data-redis底层已经解决了这个问题,而且还是异步的。
    在这里插入图片描述

持久化配置建议

慢查询

漏洞及安全配置

内存划分和内存配置

内存不足的危害

  • 导致Key频繁被删除、响应时间变长、QPS不稳定等问题。
  • 当内存使用率达到90%以上时需要警惕,要快速定位到内存占用的原因。

集群还是主从

  • 单体Redis(主从Redis)已经能达到万级别的QPS,并且也具备很强的高可用特性。
  • 如果主从能满足业务需求且不是在万不得已的情况下,尽量不搭建Redis集群。

redis lua

优点

  • 减少网络开销。可以将多个请求通过脚本的形式一次发送,减少网络时延。
  • 原子操作。Redis会将整个脚本作为一个整体执行,中间不会被其他请求插入。因此在脚本运行过程中无需担心会出现竞态条件,无需使用事务。
  • 复用。客户端发送的脚本会永久存在redis中,这样其他客户端可以复用这一脚本,而不需要使用代码完成相同的逻辑。

应用场景

  • 批量执行redis操作,需要保证原子性。

客户端执行命令

  • eval:脚本直接在redis客户端执行。
  • evalsha(开发先不了解):脚本保存到redis中,然后使用一串sha码调用。

redis.call() 与 redis.pcall()

  • 两个函数的参数可以是任意的 Redis 命令。
  • 唯一的区别是当redis命令执行结果返回错误时,redis.call()直接返回一个错误,redis.pcall()会将捕获的错误以Lua表的形式返回。

示例

语法

在这里插入图片描述

  • arg指外部传递给lua脚本的参数,可以通过ARGV[i]获取。
例子

在这里插入图片描述

springDataRedis

  • redisTemplate.execute()

补充

redis 为什么是单线程

  • cpu不是Redis的瓶颈,而是是机器内存和网络带宽。普通笔记本能轻松处理每秒几十万的请求。
  • 单线程并不代表就慢, nginx 和 nodejs 也都是高性能单线程的代表。

常见的性能问题

  • bigkey。
  • 使用批处理。
  • 机器内存。
  • 网络带宽。
  • 主从复制主从库最好在同一个局域网内,能提升速度和连接的稳定性。

redis 淘汰策略

策略

  • noeviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键。
  • volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键。
  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键。
  • volatile-lru:加入键的时候如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键。
  • volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐。
  • allkeys-lfu:从所有键中驱逐使用频率最少的键。
  • allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键。
  • allkeys-random:加入键的时候如果过限,从所有key随机删除。

默认

  • 默认是noeviction,对写的请求不再提供服务,直接返回错误。

缓存失效(guli文档)

缓存穿透

缓存雪崩

缓存击穿

分布式缓存(Redisson)(guli文档)

SpringCache(guli文档)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值