Redis的一些积累

文章讨论了Redis中的pipeline技术,用于提高效率,减少往返时间,但非原子性需注意。提到了与原生批量命令和事务的区别,以及如何禁用危险命令防止误删。此外,介绍了处理大键的方法和缓存管理,包括缓存预热、一致性问题及BloomFilter在缓存击穿场景的应用。
摘要由CSDN通过智能技术生成
  1. 快速批量添加(使用管道)
for((i=1;i<=100*10000;i++)); do echo "set k$i v$i" >> /tmp/redisTest.txt ;done;
cat /tmp/redisTest.txt | redis-cli -h 127.0.0.1 -p 6379 -a redis --pipe

管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列,先进先出特性就保证数据的顺序性。为了解决RTT往返回时,仅仅是将命令打包一次性发送,对整个Redis的执行不造成其它任何影响。
https://redis.io/docs/manual/pipelining/

  • Pipeline与原生批量命令对比
    • 原生批量命令是原子性(例如:mset, mget), pipeline是非原子性
    • 原生批量命令一次只能执行一种命令,pipeline支持批量执行不同命令
    • 原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成
  • Pipeline与事务对比
    • 事务具有原子性,管道不具有原子性
    • 管道一次性将多条命令发送到服务器,事务是一条一条的发,事务只有在接收到exec命令后才会执行,管道不会
    • 执行事务时会阻塞其他命令的执行,而执行管道中的命令时不会
  • 使用Pipeline注意事项
    • pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行中指令发生异常,将会继续执行后续的指令
    • 使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存
  1. 批量删除【好像不能选库】
redis-cli -h 192.168.10.20 -a redis  keys "k*" | xargs redis-cli -h 192.168.10.20 -a redis del
  1. 如何禁用危险命令误删误用

通过配置设置禁用这些命令,redis.conf在SECURITY这一项中,使用会报错command not found…

rename-command flushdb ""
rename-command flushall ""
rename-command keys ""
  1. big key

string ≥10kb,list、hash、set、zset个数超过500个

  • 危害
    • 内存不均,集群迁移困难
    • 超时删除,大key删除作梗
    • 网络流量阻塞
  • 找出

-i 0.1表示每隔 100 条 scan 指令就会休眠 0.1s,ops 就不会剧烈抬升,但是扫描的时间会变长
好处:给出每种数据结构Top 1 bigkey,同时给出每种数据类型的键值个数+平均大小
不足:想查询大于10kb的所有key,–bigkeys参数就无能为力了,需要用到memory usage key来计算每个键值的字节数

redis-cli -h 127.0.0.1 -p 6379 -a redis  --bigkeys -i 0.1
  • 删除,code
    • string:一般用del,如果过于庞大unlink
    • hash:使用hscan每次获取少量field-value,再使用hdel删除每个field
    • list:使用ltrim渐进式逐步删除,直到全部删除完成
    • set:使用sscan每次获取部分元素,再使用srem命令删除每个元素
    • zset:使用zscan每次获取部分元素,再使用ZREMRANGEBYRANK命令删除每个元素
  • 调优:redis.conf配置文件LAZY FREEING
    • lazyfree-lazy-server-del no改为yes
    • replica-lazy-flush no改为yes
    • lazyfree-lazy-user-del no改为yes
  1. 缓存问题

缓存预热:@PostConstruct初始化数据

缓存问题产生原因解决方案
缓存更新方式数据变更、缓存时效性同步更新、失效更新、异步更新、定时更新
缓存不一致同步更新失败、异步更新增加重试、补偿任务、最终一致
缓存雪崩服务挂掉、大量key同时失效快速失败熔断、主从模式、集群模式
缓存穿透恶意攻击,redis和mysql都不存在的数据空对象缓存、bloomfilter过滤器
缓存击穿热点key失效,全查mysql互斥更新、随机退避、差异失效时间
  1. 布隆过滤器Bloom Filter

由一个初值都为零的bit数组和多个哈希函数构成,用来快速判断集合中是否存在某个元素

  • 使用场景:
    • 缓存击穿问题,提前把缓存的key存入过滤器
    • 黑名单校验,识别垃圾邮件
    • 白名单校验,识别合法用户
  • 优点:高效地插入和查询,内存占用bit空间少
  • 缺点:
    - 不能删除元素(会导致误判率增加,存的数据会共享同一位置,存在误删)
    - 存在误判,不能精准过滤(有是有可能有,无是一定无)

guava提供的Bloom Filter将数据存入内存,用redis的bitmap也可以实现,用在分布式环境

  1. 数据库和缓存双写一致性
策略高并发多线程条件下问题现象解决方案
先删除redis缓存,再更新mysql缓存删除成功但数据库更新失败Java程序从数据库中读到旧值再次更新数据库,重试
缓存删除成功但数据库更新中…有并发读请求并发请求从数据库读到旧值并回写到redis,导致后续都是从redis读取到旧值延迟双删
先更新mysql,再删除redis缓存数据库更新成功,但缓存删除失败Java程序从redis中读到旧值再次删除缓存,重试
数据库更新成功但缓存删除中…有并发读请求并发请求从缓存读到旧值等待redis删除完成,这段时间有数据不一致,短暂存在

在大多数业务场景下,建议优先使用先更新数据库,再删除缓存的方案。理由如下:
1 先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来压力导致打满mysql。
2.如果业务应用中读取数据库和写缓存的时间不好估算,那么,延迟双删中的等待时间就不好设置。
使用canal
8. 双检加锁策略
多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。
后面的线程进来发现已经有缓存了,就直接走缓存。
9. 分布式锁
具备的条件:
- 独占性:任何时刻只能有且仅有一个线程持有
- 高可用:若redis集群环境下,不能因为某一个节点挂了而出现获取锁和释放锁失败的情况;高并发请求下,依旧性能好使
- 防死锁:必须有超时控制机制或者撤销操作,有兜底终止跳出方案
- 不乱抢:防止张冠李戴,不能私下unlock别人的锁,只能自己加锁自己释放
- 重入性:同一个节点的同一个线程如果获得锁之后,也可以再次获取这个锁
code

  1. 十大数据类型
    | 类型 | type key |
    |–|–|
    | string | string |
    | list | list |
    | hash | hash |
    | set | set |
    | zset | zset |
    | bitmap | string |
    | hyperloglog | string |
    | geo | zset |
    | stream | stream |
    | bitfield | 看具体key的value |
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值