# 技术栈知识点巩固——Redis
Posted MarlonBrando1998
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 技术栈知识点巩固——Redis相关的知识,希望对你有一定的参考价值。
技术栈知识点巩固——Redis
Redis有哪些优缺点?为什么要用 Redis ?
优点
-
读写性能优异(数据操作在内存中)
-
支持数据持久化,支持
AOF
和RDB
两种持久化方式。 -
支持事务,
Redis
的所有操作都是原子性的,同时Redis
还支持对几个操作合并后的原子性执行。 -
数据结构丰富,除了支持
string
类型的value
外还支持hash
、set
、zset、list等数据结构。 -
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
缺点
-
数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
-
Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
-
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
-
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
Redis用过哪些数据类型,每种数据类型的使用场景
-
String:最大能存储512M,
key-value
缓存,常规计数 -
List:任务执行日志,列表的存储,可以进行
List
的追加,分页等操作 -
Set:元素不可重复,可以计算集合的交集,并集,差集
ZSet的常用命令
zadd
:使用zset
存储结构
zadd score 89 张三
zadd score 90 李四
zadd score 100 王五
zadd score 99 张三
zscore score 张三
zrevrank
:排序查看
> zrevrange score 0 1 withscores
王五
100
张三
99
zincrby
:命令格式:zincrby 排行榜名称 分数增量 玩家标识
Redis缓存穿透、缓存雪崩和缓存击穿原因
- 缓存穿透:某个
key
的缓存会经常查询,有很高的并发一直在访问,如果该缓存失效,当从redis
中取值的时候,会去查数据库。解决方法是对热门的key
过期时间可以设置长一点。 - 缓存雪崩:在某一个时间段,缓存集中失效,导致全部请求去查数据库,是整个服务瘫痪。对于缓存雪崩问题可以使用集群部署,在设置
key
过期的时候可以设置一个随机值,不要在同一个时间点同时过期。可以使用双缓存策略,原始缓存和备用缓存,原始缓存失效时候,访问备用缓存,备用缓存失效时间可以设置长点。
如何使用Redis来实现分布式锁
- 查询
Redis
中对应key
的value
是否存在,如果存在则表示当前key
被占用,如果为空则可以设置一个随机值进行获取锁的操作。 - 使用命令
SETNX
:
# 结果为 1 则表示获取锁成功
setnx test 张三
1
# 结果为 0 则表示获取锁失败
> setnx test 张三
0
# 释放锁
del test
0
- 使用
Redission
实现加锁操作
Redis 持久化机制
RDB
RDB
快照是某个时间点的一次全量数据备份,是二进制文件,在存储上非常紧凑。通过save
命令手动触发或者配置自动触发。
特点
-
RDB
文件小,RDB
文件中直接存储的是内存数据速度比较块。 -
RDB
无法做到实时持久化
AOF
特点
AOF
日志是持续增量的备份,是基于写命令存储的可读的文本文件。AOF
生成的日志文件较大,需要不断AOF
。
如何选择合适的持久化方式
- 在单机环境下,如果可以接受十几分钟或更多的数据丢失,选择快照持久化对
Redis
的性能更加有利;如果只能接受秒级别的数据丢失,应该选择AOF
。
Redis持久化数据和缓存怎么做扩容?
- 如果
Redis
被当做缓存使用,使用一致性哈希实现动态扩容缩容。 - 如果
Redis
被当做一个持久化存储使用,必须使用固定的keys-to-nodes
映射关系,节点的数量一旦确定不能变化。否则的话(即Redis
节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis
集群可以做到这样。
Redis主从复制、哨兵、集群模式
Redis
集群使用详见博客:https://blog.csdn.net/qq_37248504/article/details/113861502
为什么要用redis?为什么要用缓存,在哪些场景使用缓存
- 使用Redis降低系统数据库的访问量,减小数据库的压力。使用缓存可以减少数据库的压力,提高系统的响应速度。
- 缓存使用场景:查询结果变化较少的情况。
如何解决 Redis 的并发竞争Key问题
使用 watch
watch
命令可以方便的实现乐观锁。需要注意的是,如果你的 使用了数据分片的方式,那么这个方法就不适用了。
使用分布式锁
- 使用相关的
Redis
操作API
获取分布式锁,对操作加锁操作。
使用队列处理请求
把需要处理的数据放在队列中一个一个处理。
Redis为什么是单线程的,为什么单线程还这么快?
- 基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中。
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗
CPU
。
如何保证缓存与数据库双写时的数据一致性?
- 读数据的时候先读取缓存,缓存没有的话就读数据库,取出数据放到缓存。
- 更新的时候先删除缓存,在更新数据库。
- 将读取数据和更新缓存的操作根据唯一标识放到队列中,如果发现内存中已经有一个,则轮询查看缓存是否有数据,若一段时间后还是没有数据则直接查询数据库值并返回。
redis的list结构相关的操作
-
List
:是一个字符串链表,key存在链表添加内容,key不存在创建链表 -
Lpush
:先进后出,在列表头部插入元素 -
Rpush
:先进先出,在列表的尾部插入元素 -
Lrange
:根据索引,获取列表元素 -
Lpop
:获取列表的第一个元素 -
Rpop
:获取列表的最后一个元素 -
Lindex
:根据索引,取出元素 -
Llen
:链表长度,元素个数
Reids的主从复制机制原理
-
Redis
的主从复制机制是指可以让从服务器能精确复制主服务器的数据, -
一个
master
可以有多个slave
节点 -
slave
之间可以互相同步。 -
可以用于读写分离和恢复丢失的数据需要手动配置主从节点,假如主从节点挂了,需要重新定义主节点。
Redis 一个字符串类型的值能存储最大容量是多少?
- 一个字符串类型键允许存储的数据的最大容量是512M
为什么Redis的操作是原子性的,怎么保证原子性
-
一个操作不可以再分,操作要么执行,要么不执行。
-
Redis的操作之所以是原子性的,是因为Redis是单线程的。
Redis和Redisson有什么关系
Redission
是一个基于分布式环境下具有分布式锁的redis
客户端
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.5.0</version>
</dependency>
Redis中的管道有什么用
当频繁的存储获取Redis数据库中的数据时,可以使用Redis的管道功能,将多个相互没有依赖关系的读写操作,放到队列中,使用管道对象一次性执行,可以很大程度上减少与数据库建立TCP
连接的性能损耗。
Redis事务
MULTI
:开启事务,redis
会将后续的命令逐个放入队列中,然后使用EXEC
命令来提交事务。EXEC
:执行事务中的所有操作命令。DISCARD
:取消事务,放弃执行事务块中的所有命令。WATCH
:监视一个或多个key
,如果事务在执行前,这个key
(或多个key
)被其他命令修改,则事务被中断,不会执行事务中的任何命令。UNWATCH
:取消WATCH
对所有key
的监视。
Redis事务相关命令
MULTI
:开启事务,redis会将后续的命令逐个放入队列中,然后使用EXEC
命令来原子化执行这个命令系列。EXEC
:执行事务中的所有操作命令。
> 127.0.0.1@6379 connected!
> set keyone "张三"
OK
> set keytow "李四"
OK
> multi
OK
> set keyone "王五"
QUEUED
> set keytow "test"
QUEUED
> exec
OK
OK
DISCARD
:取消事务,放弃执行事务块中的所有命令。WATCH
:监视一个或多个key
,如果事务在执行前,这个key
(或多个key
)被其他命令修改,则事务被中断,不会执行事务中的任何命令。UNWATCH
:取消WATCH
对所有key
的监视。
Redis事务的三个阶段
-
事务开始
MULTI
-
命令入队
-
事务执行
EXEC
-
事务执行过程中,如果服务端收到有
EXEC、DISCARD、WATCH、MULTI
之外的请求,将会把请求放入队列中排队
Redis事务保证原子性吗,支持回滚吗?
Redis
中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
Redis事务隔离性
Redis
是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis
的事务是总是带有隔离性的。
Redis key的过期时间和永久有效设置
- EXPIRE :
EXPIRE key seconds
设置一个key
在当前时间seconds
(秒)之后过期。返回1代表设置成功,返回0代表key
不存在或者无法设置过期时间。
- PEXPIRE :
PEXPIRE key milliseconds
设置一个key
在当前时间milliseconds
(毫秒)之后过期。返回1代表设置成功,返回0代表key
不存在或者无法设置过期时间。
- PERSIST :
PERSIST key
移除key
的过期时间,将其转换为永久状态。如果返回1,代表转换成功。如果返回0,代表key
不存在或者之前就已经是永久状态。
Redis回收算法
-
引用计数法
-
最近最久未使用算法
一个Redis实例最多能存放多少的keys?List、Set、Sorted Set他们最多能存放多少元素?
-
一个
Redis
实例最多能存放理论上2的32次方个keys
-
String
:最大512MB -
List
: 2^32-1个数据 -
Set
: 2^32-1个数据 -
Hash
:2^32-1个键值对 -
Sorted set
:与Sets类型类似,没有明确说明。应该也是2^32-1个数据
为什么要用Redis 而不用 map/guava 做缓存?
-
Map
和Guaua
使用的是本地缓存,应用重启缓存丢失。生命周期随着jvm
的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。 -
Redis
可以实现分布式的缓存,Map
只能存在创建它的程序里。 -
Redis
可以实现持久化、可以缓存大量的数据,Redis
缓存功能更加强大。
用 Redis 统计独立用户访问量
方法1
- 使用
hset
和hlen
命令
> HSET key field value
1
> HLEN key
1
Redis 全局命令
命令 | 作用 |
---|---|
keys * | 查看所有键 |
dbsize | 查看键总个数 |
exists key | 检查 key 是否存在 |
delete key | 删除某些键 |
expire key seconds | 设置过期时间 |
type key | 获取键的数据结构类型 |
以上是关于# 技术栈知识点巩固——Redis的主要内容,如果未能解决你的问题,请参考以下文章