Redis笔记

数据类型:

String Hash {"key":""val} List set {A,B,C} SortedSet

String:

指令:get set mget mset setnx(有不加) setex(时间/秒)
incr 、incrby。
应用场景:大部分业务场景都适用。
特殊使用:BitMap统计。

BitMap的使用指令:set(key,offset,value(0/1)) getbit(offset) bitcount(key) bifield bitfield_ro

Hash:

指令: hset key field value, hget key filed, hmset , hmget
应用场景:用户信息类型统计(一个属性一个key,比直接string要小)。

List:(双链表)

指令:lpush,lpop, rpush,rpop.

set:

指令sadd ,

在代码中的使用

//自行配置redisTemplate,解决序列化问题,如果不相配也可以使用Stringrdistemplate
    @Bean
    public RedisTemplate<Object ,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);//
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

          redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
//        redisTemplate.setKeySerializer(new StringRedisSerializer());
//
//        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        return redisTemplate;
    }

}

具体使用可根据具体的数据类型不同而不同
image

常见问题:
用 Jackson2JsonRedisSerializer 序列化的时候存入对象会返回LinkedHashMap?
--> 没有使用json工具读写的,默认是LinkedHashMap,使用了特定工具保存为String的,就是String

缓存穿透(解决方法一般有:布隆过滤器,缓存空对象,id校验过滤,增强id复杂度,热点参数限流,逻辑过期(需要一个锁来实现缓存重构))

缓存雪崩:同一时间段大量key同时失效或Redis服务宕机,大量服务到达数据库造成巨大压力
---> 给key添加随机TTL,添加多级缓存(nginx,tomcat,浏览器),限流降级

缓存击穿:热点数据,在大量并发的情况下时间到期,缓存重建时间长,大量并发请求打入数据库。
--> **互斥锁(优点:简单,没有额外内存开销;缺点:性能下降,死锁风险), 逻辑过期(优点:无需等待 ;缺点:一致性差(拿到锁后另外开启线程更新缓存,返回旧数据),额外缓存开销 ) **

超卖问题(更新数据时剩余数量小于0):

乐观锁(): 任务线程不安全问题不一定发送,不加锁,只是更新数据时去判断有没有其他线程对数据做了修改。 如果没有则认为安全,否则说明已经发生安全问题。
乐观锁的实现方案:
CAS:查询库存后, 更新库存的条件上加上一个 库存数量和开始查询到的一值(或大于0)

悲观锁: 认为线程安全问题一定会发生,在操作之前要先获取锁,保证按顺序指向,如 synchronized,Lock
单体项目的并发安全:
一个JVM内部通过获取某个key实现悲观锁

集群环境下用rdis实现安全
办法:Mysql Redis ZoorKeeper
Redis解决:(确保获取锁后的操作的原子性)

V1: 用setnx的特性,每个用户根据id设置一个key
前置:setnx特定的key只能有 一个线程会成功
风险:
获取锁(setnx key)成功后,释放之前万一服务出错(例如宕机),锁就永远得不到释放(del key) -> 设置锁的操作时,同时设置过期时间
如果单个线程执行时间过长,超出了过期时间,那么其他线程就可以趁虚而入。此后,最开始的线程删除key,此时有可能会有其他线程在第二个线程还在执行的时候创建key,造成不安全。

V2: 给Key设置包含线程id的val, 所有释放锁前观察当前val是否与预设值的相同,不同则不释放,相同则释放

为什么Lua脚本实现多条Redis命令的原子操作

多条reids指令同时执行存在并发修改数据的隐患,redis 的官方文档中有描述lua脚本在执行的时候具有排他性,不允许其他命令或者脚本执行,类似于事务。但是存在的另一个问题是,它在执行的过程中如果一个命令报错不会回滚已执行的命令,所以要保证lua脚本的正确性。

小妙招:

Redisson基于redis实现可重入锁(省去自己实现)

redis序列化器默认是jdk序列化器,使用默认的序列化器会造成存储时出现乱码问题

posted @   habc706  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示