随笔 - 13  文章 - 0  评论 - 0  阅读 - 1126

Redis缓存

Redis 5种基本数据类型

String

string可以做数字运算

string单个字符串最大存储512M(2^32-1)

set key value --设置key以及对应的value值

get key --获取key对应的value值

append key value --在末尾追加字符串

strlen key --字符串长度

setnx key value --键不存在才设置,nx--not exsits

incr key --递增,原子操作

decr key --递减,原子操作

msetnx key value key value ... --所有的键都不存在才设置,有任意一个键存在全部都失败

getrange key start end --截取字符串,包含start和end

setrange key start value --替换子串,从start位置开始进行替换

expire key seconds --设置key的过期时间

ttl key --查看key的过期时间

setex key seconds value  --添加数据,同时指定过期时间 (set+expire)

getset key value --返回旧值,设置新值

List

lpush/rpush key value value ..  --左侧添加/右侧添加

lrange key start end  --从左侧按范围取数据  -1表示末尾

lpop/rpop key [count]  --从左侧或右侧弹出值

rpoplpush  from_key to_key  --右侧弹出,再加入左侧

lindex key index  --按下标取数据

llen  --列表长度

linsert key before/after value new_value  --在指定的值的前后添加数据

lrem key n value  --从左侧找到n个给定的值删掉,n是0表示删除全部指定的值

lset key index new_value   --替换index位置

Set

sadd key value value ...  --设置值

smembers key   --取所有值

sismember key value   --值是否在Set中存在

scard key   --元素数量

srem key value value ...  --删除值

spop key [count]  --随机弹出

srandmember key n   --随机访问n个值(不会删除)

smove from to value   --把值从一个集合移动到另一个集合

sinter key key ...   --多个Set集合的交集

sunion key key ...  --并集

sdiff key key ...  --差集

Hash

多数情况下直接使用redis存放兼职数据

如果多个属性的对象中,有的属性要频繁修改,可以考虑使用Hash

hset key field value field value ...  

hget key field

hkeys key   --列出所有field

hvals key   --列出所有value

hincrby key field increment    --在数字上加一个值

hsetnx key field value   --不存在才添加

Zset

zadd key score value score value ...

zrange key start end    --取数据,end用 -1表示末尾

zrange key start end withscores   --取数据时同时返回得分

zrevrange key start end [withscores]   --按得分从高到低排序

zrangebyscore key min max [withscores] [limit start count]    --按分值范围取数据

zrevrangebyscore key min max [withscores] [limit start count]  --按得分从高到低排序

zincrby key increment member    --增加积分

zrem key member member ...     --删除

zcount key min max   --统计分数区间内的数据量

zrank key member    --该数据的排名(从小到大)

zrevrank key member   --该数据的排名(从大到小)

Redis事务

1、功能弱

2、Multi组队命令序列,类似mysql的begin multi后可以执行多步数据操作

3、Exec执行multi的命令序列,相当于mysql的commit

4、Discard放弃执行命令序列,相当于回滚

Redis持久化

redis内存的数据,持久化存储到磁盘,当redis重启时,可以从持久化的数据快速回复内存数据

RDB -Redis Database

1、内存数据镜像,把内存所有数据拍一个快照,把数据全部保存到一个磁盘文件:dump.rdb

2、默认在达到一定条件时才会自动保存,或者可以手动调用:save 同步保存,bgsave 异步保存

3、可以设置redis自动保存快照,redis.conf中添加配置,例如:

  save 3600 1: 1小时内,有一条数据改动

  save 300 100:5分钟内,有100条数据改动

  save 60 10000:1分钟,有10000条数据改动

RDB的优缺点:

优点:恢复数据快

缺点:持久化时存储数据效率低,不能实时存储,可能丢失新数据

写时复制:保存快照时,先写到临时文件,完成后删除dump.rdb,把临时文件改名成dump.rdb   临时文件写入失败数据损坏,也不会影响dump.rdb

dump.rdb文件修复:docker exec -it redis bash        redis-check-rdb dump.rdb

AOF-Append Only File

1、记录数据操作指令,每执行一条增删改的命令,都会实时地追加到aof日志文件 

2、默认不开启AOF,需要在配置文件中开启AOF:appendonly yes   #默认是no

AOF的优缺点:

优点:持久化效率高,实时持久化,不会丢失数据

缺点:恢复数据时效率低,aof中记录的所有命令进行重放,效率低

修复AOF文件:redis-check-aof  --fix appendonly.aof

rewrite压缩:对文件中记录的指令,能合并的指令合并成一条执行

文件大小达到min-size时触发,每增长100%时再次触发

  auto-aof-rewrite-percentage 100

  auto-aof-rewrite-min-size 64mb

官方建议使用RDB+AOF混合模式

存储:RDB完整存储内存数据    RDB之后的增量数据,使用AOF来记录增量数据

恢复:从RDB恢复绝大多数数据   重放AOF,恢复少量增量数据

默认已经开启了混合模式:aof-use-rdb-preamble yes

需要手动打开AOF:appendonly yes    #默认是no

高可用

主从

1、主从复制

2、读写分离

3、从服务器重启,可以自动从主服务器同步数据

4、主服务器宕机,从服务器会等待主服务器重启

5、主从复制原理,从服务器上线,全量复制,从服务器发送请求,主服务器rdb,将rdb文件发送给从服务器导入数据,主服务器更改数据时,自动向从服务器同步数据,增量复制

6、主-从-从结构,从服务器的从服务器,减轻主服务器数据同步的压力

7、命令slaveof ip port 作为制定服务器的从服务器 slaveof no one 从服务器转为主服务器

哨兵

1、监听主从集群,自动主从切换

2、选举依据:优先级replica-priority 偏移量 获取主机的数据数量  runid 随机的40位id的值

 Redis Cluster 集群

1、去中心化

2、配置 cluster-enable yes cluster-config-file node.conf cluster-node-timeout 15000  #失联时间

3、集群规划原则,主服务器不在相同ip,从服务器不在他的主服务ip

4、哈希槽 

cluster keyslot key 计算哈希槽值

cluster keyslot key{group}哈希槽中的数据量

cluster countkeysinslot slot 只能查看当前服务器哈希槽 

clustetr getkeysinslot slot count 获得哈希槽中存储的键  count 指定获取的数量

5、数据操作

set key value  使用key计算哈希槽 

set key{group} value 使用group计算哈希值 

mset key{group} value key{group} value ....   添加多个数据必须指定组,且是相同的组 

get key{group}  添加时有组名,获取数据时也必须有组名

6、故障恢复

主从切换,一台主机宕机,他的从服务器自动成为主机,之前的主机重启之后成为从机,一组主从全部宕机,哈希槽覆盖不全,整个集群不可用 

cluster-require-full-coverage yes 默认 

cluster-require-full-coverage no  哈希槽覆盖不全,其他服务器扔提供服务

7、缺点:不支持多键操作,不支持lua脚本,旧的集群内cluster迁移不方便

击穿、穿透和雪崩

击穿:热门数据,突然过期,访问被打到数据库上   击穿redis,打到数据库上

可能的场景:突发热门访问一个key正被大量访问,这个key过期

解决方案:预选设置热门数据,实时调整过期时间,自动续期使用锁、限流、缓存数据不存在,先把数据存入redis

穿透:Redis中没有数据,数据库中也没有数据

可能的场景:访问的数据在redis中数据不存在,大量访问非正常数据,数据在数据库中也不存在,非正常访问(黑客攻击)

解决方案:使用布隆过滤器

雪崩:大量的key集中过期,数据库访问短时激增

解决方案:多级缓存架构、自动续期、自动更新数据、即将过期的数据提前更新数据、对过期时间使用随机值,分散过期时间、锁 | 队列

布隆过滤器(二进制数组)

如果是0,表示不存在,如果是1,表示存在

当需要存入一个数据时,会通过几个哈希函数运算,将计算结果对应的哈希值的0改为1

当进行查询时,如果通过几个哈希函数计算出来的结果都是1,布隆过滤器就认为这个数据存在,只要有一个值为0就证明这个数据不存在。布隆过滤器很难去做删除操作,因为一个哈希值可能会代表多个数据。

优点:占用空间小,插入和查询速度快,保密性好,时间复杂度是O(K)

缺点:很难做删除操作,存在误判

哈希函数算法越多,误判率就会越小,占用空间就越大,性能也就越差。

Redis持久化

redis内存的数据,持久化存储到磁盘,当redis重启时,可以从持久化的数据快速恢复内存数据。

save命令和bgsave命令的区别?

save命令会阻塞redis,去生成rdb文件,直到完成文件,在此过程中,所有的客户端都被拒绝。

bgsave命令会fork一个子进程去生成rdb文件。

RDB:内存数据镜像,把内存所有数据拍一个快照,把数据全部保存到一个磁盘文件:dump.rdb

默认在达到一定条件时才会自动保存,或者可以手动调节

优点:恢复数据速度快

缺点:持久化时存储数据效率低,不能实时存储,可能丢失少量新数据

写时赋值:保存快照时,先写到临时文件,完成后删除dump.rdb,把临时文件改名为dump.rdb,临时文件写入失败数据损坏,也不会影响dump.rdb

AOF:记录数据操作指令,每执行一条增删改的命令,都会实时地追加到aof日志文件(默认不开启AOF,需要在配置文件中开启)

优点:持久化效率高,实时持久化,不会丢失数据

缺点:恢复数据时效率低,aof中记录的所有命令进行重放,效率低

官方建议使用RDB+AOF混合模式(默认开启)

存储:RDB完整存储内存数据,RDB之后的增量数据,使用AOF来记录增量数据

恢复:从RDB恢复绝大多数数据,重放AOF,恢复少量增量数据

Redis分布式锁

1.分布式锁和JAVA自带的锁的区别?

Java自带锁是进程锁,只能锁住当前服务

Redis由于资源在公共的地方,所以可以用它锁住所有订单服务

2.为什么需要分布式锁?

在微服务架构中,一个应用可能会部署多个线程,多个线程如果同时操作数据库中的一行记录,为了避出现脏数据,就要使用分布式锁了。

3.分布式锁如何实现?

想要实现分布式锁,必须要求Redis有互斥的能力,可以使用SET IF NOT EXIST,即如果key不存在,才会设置他的值,否则什么也不做,两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。加锁操作完成后,加锁成功的客户端,就可以去操作共享资源,操作完成后还要及时释放锁,直接使用DEL命令删除这个key即可。以上实现存在一个很大的问题,就是容易发生死锁。

死锁(已经获得锁的客户端一直占用锁,其他客户端永远无法获取到锁)

原因:程序处理业务逻辑异常,没及时释放锁。进程挂了,没机会释放锁

4.如何避免死锁?

在申请锁的同时,加一个锁的过期时间,在SET的同时指定EXPIRE时间,这条操作时原子的。这样又会出现新的问题,锁过期(加锁时,先设置一个预估的过期时间,然后开启一个守护线程,定时去检测这个锁的失效时间,如果锁快要过期了,操作共享资源还未完成,那么就自动对锁进行续期)| 释放了别人的锁(设置一个只有自己知道的唯一标识进去,例如自己的线程ID,如果是redis实现,要先判断这把锁是否归自己持有,只有是自己的才能释放他。释放的时候又出现了GET+DEL原子性操作,又不能同时进行了,这里使用Lua脚本,然后再让redis执行,因为Redis处理每个请求是单线程执行的,在执行一个Lua脚本时,其他请求必须等待,直到这个脚本处理完。

在Redis官网上发现了一个框架Redisson,他为Redis分布式锁提供了更好的实现和封装。

5.Redis的部署方式对锁的影响?

一般采用主从集群+哨兵的模式部署,哨兵的作用就是监测redis节点的运行状态,普通的主从模式,当master宕机哨兵实现自动切换,来保证可用性,此时就会出现分布式锁安全问题。集群模式+RedLock实现高可靠的分布式锁,RedLock算法的基本思路是:让客户端和多个独立的Redis实例依次请求加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁了,否则加锁失败。客户端只有在满足两个条件时,才能认为是加锁成功,一是客户端超过半数从redis实例上成功获取到了锁,二是客户端获取锁的总耗时没有超过锁的有效时间。

6.Redis实现高并发理由

基于内存的高速读写:Redis将数据存放在内存中,读写速度非常快,可以满足高并发的读写需求。同时,Redis还支持持久化机制,可以将内存中的数据异步地写入到磁盘上,以保证数据的持久性。

单线程模型:Redis采用单线程模型,通过事件轮询方式来处理多个客户端请求,从而避免了线程切换和锁等问题,保证了高并发下的稳定性和效率。

内部优化:Redis内部采用了多种优化技术,比如数据结构的优化、网络通信的优化、异步IO等技术,可以提升Redis的性能和并发能力。

分布式架构:Redis可以通过分布式方式,将数据分散到多个节点上,从而提高了整个系统的并发能力和可扩展性。

集群模式:Redis支持集群模式,可以将数据分散到多个节点上,从而实现负载均衡和容错性,保证了高并发下的稳定性。

7.过期数据删除策略

定性删除:将所有设置了过期时间的key放入一个独立的内部字典中,每段时间进行扫描判断是否过期(随机选20个key,删除20个key中过期的,如果超过1/4就重复上面的步骤)

惰性删除:在访问Redis获取数据时判断这个key是否过期,如果过期就立即删除

8.淘汰策略

random:随机删除数据

ttl:删除剩余有效时间最少的数据

lru:删除上次时间距离现在最久的数据

lfu:删除使用频率最少的

posted on   披着狼皮的阳  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示