redis学习记录

引入

使用数据库最大的问题是,数据库本质是IO操作,因此它耗时。
于是有人想,把数据放入内存中,这样写入还是读取就都很快。
Redis就是一款内存型数据库。
Redis 数据库不像MySQL,它没有表结构,是非关系型数据库,它整体就像是一个Map。

Redis的数据类型

String

可以包含任何数据,比如jpg图片或者序列化的对象,最大能存储512MB。
操作语句

set key value
get key
del key
keys 正则

Hash

相当于Java的Map<String, Map<String, String>>

hset zhangsan age 33
hset zhangsan weight 100
hkeys zhangsan
hvals zhangsan
hgetall zhangsan

List

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。相当于Java的LinkedList。

l -> left
r -> right
lpush
lpop
rpush
rpop
lrange list1 0 -1  查看全部

Set

Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd key v1 v2 v3 添加
smembers key  返回集合中的所有成员
srem key v1 移除集合中一个或多个成员
sdiff set1 set2 返回第一个集合与其他集合之间的差集。a b c - b e c = a
sinter set1 set2  计算两集合交集
sunion set1 set2 返回所有给定集合的并集

Sorted Set

Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。

zadd key 分数1 值1 分数2 值2 分数3 值3 ....... 向有序集合添加一个或多个成员,或者更新已存在成员的分数
zrange key 0 -1 返回区间所有成员
zrevrange key 0 -1 逆序返回,分数从高到低
zrem key 值 移除有序集合中的一个或多个成员

Redis 的key的时效性

TTL命令
EXPIRE 设置过期时间
PERSIST 设置取消过期时间

# 不存在的 key

redis> FLUSHDB
OK

redis> TTL key
(integer) -2


# key 存在,但没有设置剩余生存时间

redis> SET key value
OK

redis> TTL key
(integer) -1


# 有剩余生存时间的 key

redis> EXPIRE key 10086 
(integer) 1

redis> TTL key
(integer) 10084

微服务架构使用Redis缓存

单体服务器开发,redis随便用,但是微服务不行。
不同的子服务开发人员很容易出现撞key的情况,就会把其他开发人员的值覆盖。

解决方法:

1. 开会让大家把自己用到的key全都在会上讲清楚

2. 微服务建立一个缓存中心,就叫redis-service

cache,3
cache,3
cache,3
user-service-cache,3
user-service
push-service
sms-service
redis-service
redis

每个服务通过redis-service操作redis,在缓存中心中给每个服务要存储的key名加上对应服务的名称,使Redis的数据做了业务上的隔离,就不会出现撞key的情况了。

如果运维报警说redis服务器内存不够用了,怎么办?
keys user-service-*
redis-service
xxx公司微服务架构缓存平台

平台上用饼状图列出每一个子服务所使用的key的多少。value占用的空间大小。
使用员工号+密码登录,选择自己负责的项目名,就能查看所有的这个项目的key和value,也支持指定key查找key和value。

上述设计操作Redis需要经过两次网络请求,效率低

子服务不仅仅是一个可运行的web项目,还应该提供一个SDK。在公司局域网内的maven私服上发布redis-sdk,每个服务在项目中导入该SDK直接操作Redis。
在这里插入图片描述

代码记录
@Component
public class RedisUtil {
	//重点,这里使用@Value读取子服务的服务名,在Redis-sdk这个模块的application.yml文件中不要配置spring.application.name,这样在其他子服务的pom文件导入后,@Value才会实现谁使用就读取谁的服务名
    @Value("${spring.application.name}")
    private String appName;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;


    public void set(String key,Object value){
        ValueOperations<String,Object> valueOperations=redisTemplate.opsForValue();
        valueOperations.set(appName+"-"+key,value);
    }
    public void set(String key, Object value, long timeout, TimeUnit timeUnit){
        ValueOperations<String,Object> valueOperations=redisTemplate.opsForValue();
        valueOperations.set(appName+"-"+key,value,timeout,timeUnit);
    }
    public Object get(String key){
        ValueOperations<String,Object> valueOperations=redisTemplate.opsForValue();
        Object result = valueOperations.get(appName + "-" + key);
        return result;
    }
}

面试题

Redis存储时去掉对象头

指定序列化策略

Redis都什么时候会用到

权限校验
前端携带token(userId,roleIds)和请求路径发送请求到网关,
网关直接查询Redis

缓存一致性问题

在这里插入图片描述
最好的办法:没有写者,只有可读数据。

双写一致性问题的解决

在这里插入图片描述
如果没有读者没有问题,如果有读者需要延迟双删

延迟双删策略

在这里插入图片描述

  • 会导致睡眠时间内的缓存不一致
  • 睡眠之后再删的操作应该放到子线程,使用线程池

微服务下什么时候用Redis

中心化的策略,Redis几乎是首选
(中心化:有一个东西存放所有信息)

  1. 登录

计算MD5(UserVO->JSON)=> token
存Redis=>(token,UserVO->JSON)
之后任意一个子服务被请求,将会拿到token,那么这个token就去redis上找json->UserVO,就知道用户信息了。

情景题

1、用户请求服务器,登陆以后,拿到的token身份令牌,要求至多5个生效。(多个客户端登录)有第六个设备登录,就把最早的一个设备提掉线。

用JWT生成token
用redis存,key是userId,value是list,list<Token>
这样每一次登录,都找到对应的list看长度是否达到5,如果达到,则pop
然后把新的token给rpush进去

2、一个用户登录完成以后,30分钟没有任何操作,则用户离线。若有操作,则以这次操作的时间点,往后再延长30分钟的登录时长

用JWT生成token,在网关上拿到token了,就直接看token是否合法,合法的话,就在响应头里给他再生成一个新的token,下一次前端拿着新的token请求服务器。
缺陷:JWT生成的过程涉及非对称加密,它比较耗时
redis => hash<token,lastTime>

Redis实现分布式锁

可以使用setnx创建一个key,如果key已经存在则返回0,如果key不存在则返回1,
如果返回了1,那么就认为是获取到了锁,则立即给锁增加一个生存时间。
然后子服务执行一系列操作,执行完成以后,把这个key删除掉即可。

而上述思路有一个问题,那就是setnx创建key1和设置生存时间,这两件事不是要么都执行,要么都不执行。

为了保证这一点,我们可以使用Lua语言编写redis的执行脚本,在java中直接运行这个脚本保证操作的原子性。

缓存穿透、缓存击穿、缓存雪崩

https://blog.csdn.net/kongtiao5/article/details/82771694
缓存击穿
设置定时任务,判断是否还是热点数据进行延长时间

  • 54
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值