Redis

+++
title = ‘Redis’
date = 2023-10-03T20:31:04+08:00
draft = false
tags = [“缓存”]
description= “介绍了并发环境下Redis的解决方案”

+++

Redis学习:

通用命令

不要在主节点用:keys param 命令来查询,这查询速率很慢,单线程将会被阻塞
del param(可以是多个参数) :删除指定的key
exists param(判断key是否存在)
expire key time :设置有效期时间
ttl key :查看key的有效期

String类型

最简单的Redis数据类型,value:string,int,float;最大空间不超过512M
set key value
get key

Mset 批量 添加key-value

Mget批量获取

数值类型:incr :让变量自增加一

incrby num:按照步长增加

setnx:不存在 key才可以添加这个key

如何区分不同的key?

利用层级结构来表明table,以后的大部分业务都是用层级结构来展现和布局的!

Hash类型

哈希类型,也叫做散列,Hash的value是一个无须字典,类似于HashMap的结构。

具有field这一个字段,这是不一样的。

List类型

类似于 LinkedList(也就是双向链表)

  • 有序
  • 元素可重复
  • 插入删除快
  • 查询速度一般

Lpush key element:向左侧插入元素 返回列表长度,相应的向右边:Rpush key element

Lpop key:移除左侧第一个元素,没有则返回nil

Blop/Brpop key times:阻塞队列的插入 ,加上阻塞时间

如何用List来模拟栈?

入口和出口一起。Lpush和Lpop

模拟队列?

入口和出口不在一起。Lpush和Rpop

模拟阻塞队列?

入口出口不在一边,取的时候用阻塞Brpop/Blpop

Set类型

类似于HashSet,可以看作是value为null的hashMap。

Sadd key member:添加一个或多个元素。

Srem key member:删除元素

Smembers:获取所有元素

Sinter key1 key2:求取交集

Sdiff:求差集

Sunion:求并集

Scard:求元素个数

Sismenber key member:是否是成员

SortedSet

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

zrank key member:排名从0开始计算

zcount key min max:统计区间数量

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


Redis实际开发时序列化的问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Session共享问题,基于Redis实现的Session数据数据共享

多台Tomcat服务器,每一台都有不同的Session空间,将会存在共享问题,互相拷贝具有时间延迟和空间浪费的问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决方案:Redis数据共享

code作为key显然是不行的,将会覆盖,所有选用Phone作为key,使用Hash结构来存储,
内存占用也会比较少相对于String类型,使用随机token作为key来存储用户信息。
现在token作为登录凭证,返回token给客户端

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

缓存:浏览器缓存->应用层缓存(Redis,Nginx,Tomcat…各种缓存)->数据库缓存,根据索引来进行缓存,减少磁盘IO

优点:降低后端负载,提高读写速率,降低响应时间
成本:数据一致性成本,当数据库发生改变时,缓存未跟新,就会出现不一致,
代码维护成本也会提高,为了高可用,运维成本也会提高

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

缓存更新策略:

内存淘汰,超时剔除(低一致性),主动更新(高一致性)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

主动更新:

1调用者更新数据库时同时更新缓存;(可控性最高)

2 缓存和数据库整合为一个服务;

3 调用只操作,独立异步线程持久化到数据库,从而实现缓存和数据库一致

删除缓存(无效操作太多)而不是更新缓存,单体项目需要将缓存和数据库放在一个事务,考虑线程安全
Cache Aside Pattern(解决线程安全问题)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

缓存穿透:

请求客户端数据中,缓存里面和数据库里面数据都不存在,请求都打到数据库上面了

解决办法:布隆过滤器(内存占用少),缓存空对象或者null(额外内存消耗,可能造成短期不一致)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
主动添加 对ID的复杂度

缓存雪崩

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
很多key同时失效

缓存击穿

热点key突然失效,无效热点数据给数据库带来巨大压力

1:使用互斥锁来写入缓存,但是互相等待时间比较长,性能较差

2:逻辑过期TTL=-1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

选择一致性还是可用性

全局唯一 ID生成器
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

UUID:没有满足特性 ,RedisId:数字类型,snowflake:算法,维护机器ID

多线程下高并发超卖问题是怎么发生的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当线程扣减时候,多线程查询库存,扣减库存之前,直接一个数据用两次,使得出现并发安全问题。

锁的介绍:

悲观锁:

悲观锁

例如synchronized 和lock,认为线程安全问题一定会发生,在操作数据之前一定要获得锁之后才执行

乐观锁

认为线程安全问题不一定会发生,多数情况不发生,不加锁,
在线程做数据更新时进行数据判断,看之前的判断数据是否发生修改,性能相较于乐观锁好

那怎么判断之前的数据是否发生了修改呢?

1:版本号法(最广泛)
给数据加上版本号,同时在修改时不仅要查询版本号同时还要修改版本号

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2:CAS方法,假如数据本身具有变化,那么数据本深就可以作为版本号

3:分段锁,解决成功率较低的问题,实际秒杀还要对秒杀进行优化,不对数据库造成压力

集群模式下的并发安全问题:

当出现集群和负载均衡时,可能出现交叉执行,锁失效了,这就是分布式来解决这个问题

锁监视器不是同一个

出现了两套JVM,锁监视器具有不同的,这将会导致出现并发安全问题

==》解决办法:分布式锁

一人一单

分布式锁

实现原理:不同的JVM采用同一个JVM

分布式锁特点:多进程可见同时时互斥的锁,高可用性,高并发(高性能),安全性,是否会产生死锁

是否满足可重入性?(不是重点)

分布式锁的实现

实现方式:Mysql Redis Zookeeper

mysql:利用mysql本身的互斥锁机制,redis:利用setnx这样的互斥命令,利用key的过期时间来解决安全问题。

zookeeper 利用唯一节点和有序性来实现互斥锁。高可用性还是比较好的,安全性较好

基于Redis实现分布式锁:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

127.0.0.1:6379> help set

  SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

127.0.0.1:6379> set lock thread EX 10 NX
OK
127.0.0.1:6379> set lock thread EX 10 NX
(nil)
127.0.0.1:6379> ttl lock
(integer) -2

实现将会是非阻塞式的分布式锁

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

极端情况线程出现并发安全问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决办法:释放锁的时候需要进行检查,看自己的锁标识是否和之前获取的一样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

只要redis锁发生了超时释放就有可能发生并发问题。

例如FullGc时,发生阻塞就会出现并发问题,所以释放锁和判断锁标识必须是原子性的,必须同时

用Lua脚本来解决原子性问题

利用看门狗解决锁超时释放的问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Redisson问题(呵呵,这是一个把分布式锁实现好的开源框架)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

redisson 分布式锁原理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可重入:利用hash结构来记录线程id和重入次数,类似于ReentryLock

可重试:利用信号量实现等待和获取锁失败的重试机制

超时续约:利用看门狗,在获取锁之后,每隔一段时间,就自动续约,锁满血复活。

分布式锁的主从一致性问题。

利用redisson的multi lock来实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

利用Redis来优化秒杀

使用Set类型,解决唯一性问题。lua脚本来解决锁释放和事务提交的原子性问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将下单信息添加到阻塞队列里面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Windows相关命令:

查找并记录需要杀死的进程号码: netstat -ano

查找端口:netstat -ano|findstr [Port]

查找名称:tasklist |findstr [PID]

杀死进程: taskkill -f -pid [PID]


消息队列【Message Queue】:【RabbitMq Kafka RedisQ】

基于Redis实现的异步阻塞队列存在jvm内存溢出问题,基于此实现了消息队列。

消息队列:存储和管理消息,称为消息代理(message broker)

生产者:发送消息到消息队列

消费者:从消息队列中获取消息并处理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基于Redis-List结构来模拟消息队列

BLpush+BRpop/BRpush+BLpop

独立于JVM,不依赖于机器,具备数据持久化,满足消息的有序性。
无法避免消息丢失,只支持单消费者。

基于PubSub的消息队列

发布-订阅模式

支持多生产和多消费:publish subscribe,psubscribe匹配使用正则表达式

不支持消息持久化,无法避免消息丢失(当客户端宕机时,不接受消息,消息将会丢失),消息堆积有上限。

基于Stream的消息队列。基于Redis-5.0实现

XADD key [队列是否创建] [消息队列最大上限] [ID] [filed] [value]
XREAD [count] [block sec] streams [key] [id]
xgroup creat key groupName ID
消息可回溯,可阻塞读取,可被多个消费者读取,有漏读的风险
单词:pending:待定

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

消费者组:

消息分流 消息标识(确保消息都会被消费) 消息确认(消息处于pending状态,存入list中,需要得到确认 )

xgroup create/destory/delconsumer key groupName ID [“mkstream”]

基于stream来实现的消费者组,
读取消息都是从pending-list中读取消息,实现方法是通过id进行筛选

消息读取之后必须进行确认,参数为消息id,确认之后消息id将会被消息队列移除

消费者组的名称一般企业环境下都是写在yml文件里面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三种消息队列List PubSub Stream 解决方案的区别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发布达人探店

对两张表去进行表的设计:

利用Zsort来作为点赞和排行榜数据结构
相关命令:zadd member score ,zscore member,zrange key from to

关注推送,Feed流,提供沉浸式体验

常见的两种实现模式:

timeline:核心需要带上时间戳,不做内容筛选,信息全面,实现相对简单,但是信息噪音比较多

实现方式:拉模式,推模式,推拉结合

拉模式(读扩散):缺点是延迟高

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

推模式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

推拉结合:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

收件箱使用redis来实现,查询redis查询收件箱数据时需要实现分页查询,list,soretedset,数据的角标会发生变换,按照传统的分页方案将会出现错误

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

智能排序:针对用户使用习惯做一些算法,尽量接近用户使用习惯,但当用户习惯与算法不对称时,将会出现反作用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值