关于内存、缓存、redis缓存

项目中期用到 对于操作记录的记录
当用户登录后,通过前端传进来的code,将装有用户信息的东西(token,username,userrealname)封装成dto实体返回给前端。
解决方案一:使用字典先将东西写进内存,只要不重启就不会丢失。
解决方案二:内存缓存,此前公司封装过方法
解决方案三:Redis缓存。我要抽时间去学习啊
D:给前端返回什么,前端就会带什么。

07、string

操作是原子性:不会被线程打断的操作。
单线程多路io复用
java中i++是不是原子操作

08、字符串操作

mset
mget 同时设置多个键值对
msetnx
如果key已经存在了,不会成功。
getrange

setex age 20 value30 <过期时间>
ttl age
getset 花样真多
底层,简单的动态字符串,arraylist
字符串最大长度不能超过512M

09、redis列表 list

底层实际是双向链表
lpush 从左边插入数据 挤
lpush ke v1 v2
lrange k1 0 -1
rpop

list数据结构 quickList
元素较少 使用ziplist
将多个压缩列表用链表形式链接
使用双向指针

10、set集合9

自动排重

smembers k1 取出集合中所有值

11、hash13

第三种方式:
field value 映射关系
hset 向hash添加数据
hset user:1001 id 1
hget key1 field
hmset user:1002 id 2 name lisi age 30
hkeys
hexists
hsetnx 存在不能添加

12、Zset

没有重复元素 有序
每个成员都关联了一个评分
zadd topn 200 java 300 c 400phh 500 mlysql
将一个或多个加到有序集合中
zrange topn 0 -1 withscores
取出来所有
zrangebyscore topn 300 500 withscores
zrevrangebyscore topn 500 200 withscores
zincrby topn 50 java
zrem 删除指定值

zrank topn java 查看java所在的排名

实现文章访问量排行榜

底层数据结构
一方面等价于Map<String,int>

hash field value:score
另一方面,跳跃表
效率堪比红黑树 分三层 从第二层开始找
怎么有点像二分法
有序链表

13、配置文件详解

vi /etc/
支持远程连接
protected-mode no
#bind注释

tcp-backlog 511
backlog是一个连接队列,backlog队列总和等于未完成三次握手队列+已完成三次握手队列

timeout 0
永不超时
tcp-keepalive 300

pidfile
loglevel 日志级别
debug 开发环境中可以看到更详细信息
notice 生产环境

密码 SECURITY
limits 客户端最大连接数

14、发布订阅6

订阅者 s1 接收到所有消息

redis客户端可以定义任意数量的频道

发布者 p1
1、打开客户端,订阅频道1
SUBSCRIBLE channel1
2、发布
publish channel1 hello

15、bitmaps15

bitmaps本身不是一种数据类型,是字符串,
可以对字符串的位进行操作。
数组下标:偏移量
setbit <>
setbit users:20200202 1 1
//添加一个
getbit users:2020202 1
//获取偏移量
bitcount
//统计被设置为1的字符串数量

16、hyperLogLog8

17、geospatial6

18、jedis操作 测试23

对于zset了解不够

19、jedis演示

随机生成六位验证码

public class PhoneCode {
	public static void main(String[] args) {
		String code = getCode();
		System.out.println(code);
	}

	public static String getCode(){
		Random random=new Random();
		String code="";
		for(int i=0;i<6;i++){
			int rand=random.nextInt(10);
			code+=rand;
		}
		return code;
	}
}

在这里插入图片描述
setex()方法

//发送验证码放到redis中

String vcode=getCode();
jedis.setex(code,120,vcode);
jedis.close();

//验证码校验

public static void getRedisCode(String phone,String code){
	//从redis获取验证码
	Jedis jedis=new Jedis("9394802",6379);
	//验证码
	String codeKey="VerifyCode"+phone+":code";
	String redisCode=jedis.get(codeKey);
	//判断
	if(redisCode.equals(code)){
		sout("成功");
}
	else{sout("失败");}
}

听了一遍 没有能力给别人讲怎么做。

20.整合springboot

引入依赖
配置内容
创建springboot

配置文件 进行配置

创建redis配置类
com.atguigu.redis_springboot

创建redisTestController

java写法很不习惯

@Autowired
private RedisTemplate redisTemplate;
@GetMapping
public String testRedis(){
	//设置值到redis
	redisTemplate.opsForValue().set("name","lucy");
	//从redis获取值
	String name=(String)redisTemplate.opsForValue().get("name");
	return name;
}

完成整合

21、事务和锁机制

是一个单独隔离操作
不会被其他客户端发来的命令打断
multi 开启命令
QUEUED 组队
exec 执行
组队时有任何命令失败,都不会执行。
情况二,组队成功,哪个失败哪个不执行。

22、事务冲突

如何处理
1、悲观锁 每次别人拿锁都认为会取出数据
每次操作前先上锁 别人不能操作
传统关系型数据库常用 行锁
效率低
2、乐观锁
checkandset
通过版本号操作,
加上数据版本号
除了更新数据外,版本号进行同步更新。
乐观锁适用于多读的应用类型,可以提高吞吐量。

应用:抢票,都抢到 只能由一个人成功

23、事务和锁机制 8

24、秒杀案例

写了
但是没有保存下来
回想过程

判空 两者都需要
key值拼接 这里的目的为了什么其实不太理解
注意 prodid使用string uid使用set

判断库存是否大于0
判断用户表是否存在用户 已经存在不让买

25、秒杀

模拟多并发过程
上面的代码面临问题
以及如何解决问题
模拟请求
问题:结束了 后面还会显示成功了
库存小于0,不能解决并发问题
连接超时问题,不能同时处理2000个问题。
如果请求一直等待,出现连接超时问题

26、超卖和超时问题

连接池解决连接超时问题
工具类 连接池

2、通过连接池得到redis对象

JedisPool jedisPoolInstance=JedisPoolUtil.getJedisPoolInstance();
Jedis jedis=jedisPoolInstance.getResource();

类似于数据库连接池
超卖问题,没有事务
通过乐观锁解决

//监视库存
jedis.watch(kcKey);
将秒杀过程添加到事务中
7、

Transaction multi=jedis.multi();
//组队
multi.decr(kcKey);
multi.sadd(userKey,uid);

//执行
List<Onject> results=multi.exec();

if(results==null||results.size()==0){
	sout("秒杀失败");
	jedis.close();
	return false;
}

总结,使用 watch监视,进行组队,进行执行。

27、库存遗留问题解决

库存遗留 乐观锁造成
1购买 修改版本号
剩下的1999人不能做其他操作
redis默认不能使用悲观锁
lua脚本
可以被调用,也可以反过来调用C函数

本身不独立使用
将复杂多步骤的redis脚本写成一个脚本、
只支持2.6以上版本、
有一定的原子性,不会被其他命令插队

java代码调用lua脚本、

String shal=jeddis.scriptLoad(secKillScript);
Object result =jedis.evalsha(shal,2,userid,prodid);

没有get到,
使用lua脚本,可以、

28、持久化 rdb

数据写到硬盘中
指定时间间隔将内存的数据集快照写到磁盘
底层执行过程
单独建立子进程进行持久化,将数据写到临时文件中。写时复制技术
dump.rdb
首先创建子进程,fork
建立临时空间(文件) 把数据同步进来 再覆盖到rdb文件中
为什么?同步过程 服务器挂了 数据不完整 缺失
保证数据完整性 安全
写时复制
启动目录 变化 dump.rdb
检查完整性、
Save:写操作次数
约定一个规则
在指定时间间隔内将内存中数据集快照写入内存。

适合大规模的数据恢复。
fork 克隆 膨胀两倍空间
有可能造成数据丢失
最后一次持久化时数据可能会丢失。

29、rdb2

vim /ect/redis.conf
save 20 3
redis-cli

30、aof 25

append only file
日志形式记录每个写操作,只许追加但不可以改写文件。
为什么rdb没有数据
既有rdb 又有aof 默认取aof数据

删除appendonly文件
aof恢复 当你重启时,读取

异常恢复
对文件进行修复
redis-check-aof -fix redis-cli redis-server

启动
redis-server /etc/redis.conf
redis-cli
keys *
同步频率配置 appendfsync always
每次写入都会立刻记入日志
appendfsync everysec
appendfsync no 不主动,交给操作系统

压缩
使用aof子进程
触发机制:文件大于64MB的两倍时候
aof持久化流程 客户端请求命令被追加到aof缓冲区
存粹用缓存 两者都不用
aof有bug

31、主从复制

11/8晚上 公司
主机数据更新后,根据配置和策略,
读写分离 性能扩展 其中 master以读为主,slave以写为主
容灾快速恢复
一主多从
只能有一台主服务器
set a1 v1
set a1 v111
配置集群效果
一台主机 多台从机

32、搭建一主多从20

模拟一主两从
mkdir /myredis
2、复制redis,conf文件
cp /etc/redis.conf /myredis/redis.conf
3、使用不同端口启动
配置一主两从 创建三个配置文件
redis6379.conf
4、在三个配置文件中写入内容
include /myredis/redis.conf
/appendonly no
vi edis6379.conf
include /myredis/redis,conf
打开另一个客户端
配置pid位置
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb

cp redis6379.conf 6380.conf
vi redis6380.conf

5、启动三台
redis-server redis6379.conf
ps -ef |grep redis
kill -9 1055??

info replication
查看当前主机运行状态
redis-cli -p 6379
clear
cd /myredis
redis-cli -p 6380
info replication 此时都是主机
slaveof
作为当前主机的从机
在从机上执行slaveof 主机ip 端口号
11、9早上在公司
相当于在主机做写操作 从机中读操作 复制

33、主从复制原理一主多仆12

keys *
shutdown 关机
如果中间断了,6380会接收到效果吗
redis -server redis6380.conf
redis-cli -p 6380
从头复制 重启需要重新加入
shutdown 主服务器挂了
从服务器仍然是从服务器
redis-cli -p 6379
重启之后王者归来

主从复制 原理

1、从服务器连接上主服务器后,从服务器向主服务器发送进行数据同步消息。
2、主服务器接到从服务器发过来的同步消息,把主服务器数据进行持久化,rdb闻不见,把rdb文件发送给从服务器,从服务器拿到rdb进行读取。
是从服务器主动进行。
3、每次主服务器进行写操作后,和从服务器进行数据同步。

34、薪火相传和反客为主 9

一个人管理20人
分小组 分层治理
缺点:从服务器挂了,主服务器无法连接上后面的
依然遵守之前的规则
反客为主 小弟晋升为大哥
slaveof no one 可以将从机变成主机
但是 需要手动完成
全自动模式 哨兵

35、哨兵模式20

后台监控 主机是否故障
其实我上面写的笔记没有什么意义,学习方式的问题。
有些东西知道运行过程就可ui了。

1、新建一个配置文件
sentinel monitor mymaster 127.2.2.2 6379 1
1 指的是有多少个哨兵同意迁移的数量
redis sentinel /myredis

redis-sentinel

选举 slave_priority

切换
新皇登基
info replication

复制延时
所有写操作都是在master操作
优先级靠前 优先选举
slave-priority 100 值越小优先级越高
偏移量最大的
runid 随机生成

36、redis6集群

容量不够 如何扩容、
并发写操作,如何分摊
使用集群
一、代理主机方式
代理服务器 根据请求 请求包含什么 访问什么
缺陷:某台挂了,加个从机,如果代理服务器挂了,那也加一台服务器;至少需要8台服务器

二、redis3.0 无中心化集群
任何一台服务器都可以作为集群入口
可以互相连通
实现了对redis的水平扩容
每个节点存储总数据的1/n

37、搭建redis集群23

rm -rf dump63*
ll
修改配置文件 创建6个redis服务
约定主机从机
vi redis 6379.conf
daemonize yes
redis cluster 配置修改
三个
2、设定节点配置文件名字
3、设置失联时间

删除 rm -rf redis6380.conf
rm -rf redis6381.conf
复制出另外五份 根据6379
cp redis6379.conf redis6380.conf

修改具体端口号中内容 vi redis6380.conf
这些不用记 看看就行
:%s/6379/6380
:wq! 退出

一主一从
使用集群策略连接,设置数字会自动切换到相应的写主机。
redis -cli -c -p 6379
cluster nodes 查看集群中数量
至此 集群搭建成功,其实没有听懂

38、集群操作和故障恢复

尽量保证每个主数据库运行在不同的ip地址,每个主库 从库在不同ip地址
为什么:假设三台在同一个,挂了,全坏了。
服务器同理。
保证集群的高可用
slots 是:插槽 数据库中的每个键
听到4分多
数据库中每个键都属于插槽中的一个
redis集群16384插槽

set k1 value1
k1计算所在的插槽
集群是用公式计算位于那个插槽
把值平均分担到不同位置
set k1 v1
mset name lucy age 20 adress china
同时插入多个值
把值分成一组 mset name {user} lucy age{user} 20
为什么redirect

cluster keyslot k1
cluster countkeysinslot 12706
只能看自己插槽中的值
set k3 v3

redis-cli -c -p 6380
cluster nodes
6379重启 变成从机

主机从机都挂掉 根据配置决定
cluster-require-full-coverage no
其他可以提供服务

需要再看一遍

39、集群的jedis开发

new HostAndPort("");
JedisCluster jedisCluster=new JedisCluster();

jedisCluster.Set(“b1”,“value1”);
String value=jedisCluster.get(“b1”);
无中心化 放一个

实现扩容 分摊压力 无中心化配置简单
不足:多建操作不被支持 组
lua脚本不支持 事务不支持

40、缓存穿透

1、应用服务器压力突然增大
2、redis命中率降低
3、一直查询数据库

1.redis查询不到信息
2.出现很多非正常url访问

设置可访问白名单
bitmaps类型定义可以访问的名单
布隆过滤器 命中率不高
4.进行实时监控 设置黑名单限制服务

41、缓存击穿 5

1、数据库访问压力瞬时增大
2、redis并没有大量key过期
3、redis正常运行

原因:redis某个key过期,大量访问使用这个key
解决:1、预先设置热门数据
2、实时调整
3、使用锁

42、缓存雪崩

数据库压力变大 服务i去崩溃
在极少的时间段 查询大量key集中过期情况。
构建多级缓存架构
nginx缓存+redis
使用锁或者队列
设置过期标志更新缓存 设置提前量
将缓存时间分散
随即增加一个随机值

43、分布式锁

单体应用
分布式集群

锁对集群分布式都有效
如何实现:
基于数据库实现

基于缓存
setex key second value
setnx users 10
只有等它释放后才可以进行后续操作
del users 20

给锁设置过期时间
setnx users 10
原子操作
3、上锁后断电 过期时间失效
上锁同时设置过期时间
set users 10 nx ex 12
将上锁和过期时间同步执行

44、分布式锁

很懵逼 什么是ab测试
我他妈的块困死了

如何设置 a不能释放b
使用uuid防止误删
第一步 set lock uuid nx ex 10
uuid表示不同操作
第二步 释放锁 首先判断 uuid和要释放的锁uuid是否一样
redisTemplate.opsForValue()

String uuid=UUID.randomUUID().toString();
//获取锁
Boolean lock=redisTemplate.opsForValue().setIfAbsent("lock",uuid)

45、分布式锁

总算没那么困了
删除操作缺乏原子性。
谦虚 自信
场景:正要删除,还没删除,锁到了过期时间。自动释放,然后这会a就会去删除b的锁。
发生这种事的原因是:目前操作中没有原子性
lua脚本 保证删除的原子性

互斥性 不会发生死锁
加锁解锁必须是同一个操作人
加锁解锁必须有原子性

46、新功能11

允许根据可以执行的命令和可以访问的键来限制某些连接

47、课程总结

常用五大数据类型
4、配置文件
持久化操作配置
5、发布订阅 命令行
6、新数据类型
7、jedis 操作
模拟验证码发送
能写出来
8、springboot整合
9、事务 乐观锁 悲观锁
10、持久化操作 rdb 数据不敏感
11、aof优先
12、 主从操作
13、集群 3主3从
14、常见问题 分布式锁
15、新功能

关于redis的其他扩展

看了一个诸葛的视频
购物车使用哈希实现 等于双层的字典
外层的key是 用户id
内层的key是 商品id 内层value是商品数

购物车
添加商品 hset cart:1001 10088 1

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用提到了Redis,它是一种常用的分布式缓存系统。Redis是一个开源的、基于内存的数据存储系统,它可以用作缓存、消息队列、持久化等多种用途。由于Redis具有高性能、高可用性和可扩展性,所以在分布式环境中广泛应用于缓存数据的存储和访问。Redis使用键值对的方式存储数据,并支持各种数据类型的操作,如字符串、哈希、列表、集合和有序集合等。在分布式缓存中,Redis通过在内存中存储数据,提供了快速的读写操作,以加速应用程序的性能。同时,Redis还具有分布式锁的功能,可以保证在分布式环境中的并发访问的一致性。引用提到了Redission,它是一个基于Redis实现的分布式锁框架。Redission提供了多种分布式锁的实现方式,包括基于Redis的分布式锁。通过使用Redission,可以很方便地在分布式环境中实现锁机制,保证数据的一致性和并发访问的正确性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Redis(分布式缓存详解)](https://blog.csdn.net/chenjiap/article/details/131630981)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值