目录
正确的选择数据类型
都使用string去存储数据存在哪些弊端
- 浪费存储空间,key也是需要存储空间的
- 管理维护麻烦,Redis中存在着大量的KV对象
- key冲突比较高
- 建议使用hash存储对象
命名策略
业务名称+工程名+模块名+(有意义的)键名
常用的数据类型及其适用场景
- string
- 应用最广泛的数据类型,例如计数器,session等键值"独立"的数据
- hash
- 存储结构化(对象)的数据,KV共同构成一个对象的信息
- list
- 队列,栈,有界队列
- set
- 去重,无序的数据集合,在类似于社交的业务功能上有广泛应用,例如:共同关注,共同喜好,数据去重
- sortedset
- 带有权重的集合,在类似于排行榜业务上有广泛应用,且可以视线范围查找
用了事务却没有发生回滚
redis事务
redis事务的两类错误
为什么redis不支持回滚
- 失败的命令是因为编程错误造成的,这些错误应该在开发的过程中被发现,所以不支持回滚
- 如果检测到了事务命令的错误应该不加思索的使用discard放弃这个事务
redis性能上不去,可能是有 big key
big key以及造成的危害
- 数据量大的key,比如字符串的Value值非常大( > 10kB),哈希,列表,集合,有序集合元素多(元素个数>5000)
- big key造成的危害
-
内存不均:针对redis集群来说,不确定存在集群的哪一台机器上,或造成不同的机器使用内存不均的情况
-
超时阻塞,redis操作big key比较耗时,阻塞redis的可能性就会变得很大
-
网络流量阻塞,每次获取要产生的网络流量比较大
-
过期删除,过期删除时间长,可能会阻塞
-
迁移困难:备份和导入都会导致阻塞,迁移困难
-
big key是如何产生的
- 社交类场景
- 粉丝列表,对于明星或者大V来说,需要特殊的设计,否则,就成为了BigKey
- 汇总统计类场景
- 每天都会产生报表数据,报表数据汇总到一个key里面,日积月累就成为了BigKey
- 日常缓存类场景
- 对DB中的数据进行缓存,大表(存在大字段)很可能会产生BigKey
如何发现BigKey
- redis-cli提供了 --bigkeys来查找bigkey:给出了每种数据结构的top 1 bigkey,同时也给出了每种数据类型键值个数以及平均大小
- 如果想查询redis中大于10KB的所有key,--bigkeys就无能为力了
- redis4.0开始提供了memory usage命令可以计算每个键值对的字节数(Redis为了保存这个键值对一共需要消耗的内存,包括指针开销)
删除bigkey
Redis怎么出现了内存耗尽
Redis服务器内存耗尽的场景
内存耗尽的结果是只能读而不能写
- 业务不断发展,缓存数据不断增多,需要消耗Redis内存
- 无效(过期)的数据没有及时清理,需要消耗Redis内存(优化点)
- 没有对"冷数据"(不经常访问的用户)进行降级需要消耗Redis内存(优化点:直接从redis中删除,当发送请求时从mysql中直接读然后再写到mysql中);
将key标记为Volatile(易失的)
- ttl key 查看过期时间
- expire key seconds 给key增加一个过期时间
- rename beforekey afterkey 不会改变过期时间
- presist key 将这个key过期时间移除,标记为持久的key
Redis的过期删除策略
- 定时删除
- 为每一个设置了过期时间的key都会创建一个定时器,一旦到达过期时间就会立即删除
- 惰性删除
- 当访问一个key时,才判断key是否过期,过期删除
- 定期删除
- 每个一段时间,扫描Redis中过期key字典,并删除部分过期的key
- redis使用了定期+惰性删除
有了过期机制以后内存还是不够用
设置了过期Redis服务器内存还是不够用原因
- 业务缓存数据需求量大,占用大量的内存空间
- 过期的key虽然有很多,但是不能"及时失效",仍会有大量的key堆积在内存中,导致Redis内存耗尽
- 有没有办法让Redis主动帮我们淘汰"一些数据"呢??
Redis的内存淘汰策略
-
Redis的内存淘汰策略,是指内存达到maxmemory极限时,使用某种算法来决定清理掉哪些数据,以保证新数据的写入
-
最常用的内存淘汰策略
-
Volatile:只会针对带过期时间的key进行淘汰
-
volatile-lru:最近最久未被使用的key
-
volatile-random:随机的key
-
volatile-ttl:根据key的剩余时间,越小优先会被淘汰
-
- allkeys:策略会针对所有的key进行淘汰
- allkeys-lru:最近最久未被使用的key
- allkeys-random:随机的key
- noeviction:默认的淘汰策略,当redis满了之后就不能提供写服务,但是可以提供读服务
-
- 内存淘汰策略的执行时机:Redis会在每一次处理命令的时候判断当前是否已经达到了内存的最大限制,如果达到限制,则使用对应的算法去处理需要删除的key
- 配置Redis:redis.conf maxmemory 10240000 maxmemory-policy noviction
- 如何选择??
- 如果拿redis做缓存,那应该使用allkeys下的淘汰策略
- 如果你还想同时使用redis的持久化功能,那就是用volatile下的淘汰策略
如何解决频繁的命令往返造成的性能瓶颈
redis客户端和服务端的交互模型
- redis是基于一个request,一个response的同步请求服务
- 数据包往返于两端的时间被称为RTT
redis的pipeline的交互模型
- 减少客户端与服务端通信的次数
- pipeline是基于队列实现的,保证了先进先出
调用redisTemplate.executePilelined方法.重写里面的RedisCallback<Object>里面的doInRedis方法,在该方法里面首选需要根据参数connection打开pipeline(connection.openPipeline),通过connection添加我们的命令.注意:不能关闭Pipeline,不然到最后我们得不到返回值,需要返回null
Redis pipeline与原生批量命令对比
- 原生批量命令是原子性,Pipeline是非原子性的
- 原生批量命令一次只能执行一种命令,Pipeline支持批量执行不同命令
- 原生批量是服务端实现,Pipeline需要服务端和客户端共同完成
- 需要注意的是:Redis事务具有隔离性,在执行过程中不会穿插其他客户端发送的命令
使用redis pipeline需要注意什么
-
使用pipeline组装的命令个数不能太多,不然数据量过大
-
pipeline会按照缓冲的顺序执行,但是可能会穿插其他客户端发送来的命令,即时序性不能保证
-
pipeline执行中间某一个指令出现异常,将会继续执行后续的指令,即不能保证原子性
配置好持节化机制
redis为什么需要持久化
- 高并发场景只使用redis作为存储设备,需要保证数据不会丢失
- 通常的应用场景虽然会同时把数据写入Mysql,但是直接从Mysql中恢复数据性能低下,且确实选择性(不知道之前的redis存储的数据,是选择哪些恢复还是全部恢复)
RDB
RDB持久化触发原理
手动触发
定时触发
AOF的持久化配置
AOF重写
从持久化中恢复数据
企业级的恢复策略
缓存穿透隐患
通用的业务存储架构
缓存穿透的含义以及带来的影响
怎么解决缓存穿透
出现缓存雪崩怎么办
为什么会出现缓存雪崩
缓存雪崩会带来什么问题
怎么解决缓存雪崩