Redis相关知识

Redis是什么

Redis是一个基于内存的key-value数据库。(内存:性能高,nosql:不实用sql作为查询语言)

特性

  1. 它支持数据持久化,可以将内存中的数据保存在磁盘中,重启时可再次加载进行使用。
  2. 有丰富的数据结构(string,list,hash,set,zset),不止5中
  3. 支持数据备份(主从复制)

单value值可存储的最大限制为1GB

有丰富的api,可设置过期时间

数据类型

String

简单的key-value类型,value值可以是string,也可以是数字。可以用来做计数器(微博数,粉丝数,限制请求数)

incr key如果key不存在,值会被初始化为0,然后在执行incr操作

Hash

适合存储对象,value是一个string类型的filed/value映射表

List

list是一个双向链表,支持反向查找和遍历

Set

set可以进行自动排重,可以判断某个成员是否在集合内,还可以实现交集、并集、差集操作(共同关注,共同粉丝等)

Sorted Set

比set多了个权重参数score,使得集合中的元素能够按照score进行排列(比如礼物排行榜,或者点赞排行榜)

能做什么

缓存

什么是缓存呢?缓存就是在内存中存储的数据备份,当数据未发生变化时,直接从缓存中读取数据,从而避免直连数据库进行查询操作,这样大大降低了数据库的读写次数。并且从内存中读取数据要比从数据库查询速度快。

我们使用redis主要用作数据缓存。(基于redis的特性,选用其作为缓存)

什么数据需要保存在缓存中?(经常被访问的,增删少的数据,比如官网首页数据)

排行榜

适用redis的SortSet数据结构可以很方便

计算器/限速器

利用redis的原子性的自增操作,可以统计类似用户点赞数、用户访问数等。(这类操作频繁,如果通过数据库实现功能,频繁的读写会对数据库带来很大的压力)

限速器的场景是限制某个用户访问某个api的频率,例如抢购,防止用户疯狂点击带来不必要的压力

好友关系

利用集合的一些命令,通过求交集、并集、差集,可以实现获取共同好友、共同爱好等功能

简单消息队列

除了redis自身的发布/订阅模式,也可以利用list来实现一个队列机制。比如将一些通知类消息,邮件通知,短信通知等放入队列中,其他模块进行处理,使应用进行了解耦。

使用list结构作为队列,rpush生产消息,lpop消费消息。到lpop没有消息的时候,就适当的sleep,或者使用blpop,在没有消息的时候,它会阻塞直到消息到来。

有主题订阅模式,可以实现消息队列。但在消费者下线的情况下,生产的消息会丢失。得使用专业的消息队列。

lpush mylist插入队列  lrange mylist 0 -1 查询队列  rpop mylist弹出元素(需要不停调用rpop方法才能知道是否有消息)

brpop/blpop实现阻塞读取

session共享

用户登陆的session是保存在服务器的文件中,如果是集群服务,同一个用户的请求可能落到不同的服务器上,这就会导致用户登陆失效,需频繁登陆,影响体验。使用redis来保存session,无论用户请求哪个服务器都能够获取到对应的session信息。

分布式锁

使用setNx命令来争抢锁,抢到后,给一个失效时间,防止忘记锁释放

Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。

不能做什么

面试期间,有的面试官询问过,可不可以做数据库。

可以做,但是不建议。

  1. Redis虽然有持久化的功能,但最终是通过将数据读取到内存上,来进行操作的。内存与硬盘相比,价格高,且空间小,不适用(仅作为数据库保存在内存中纯属资源浪费,成本也会过高)
  2. 它的持久化方案并不能保证数据落地(持久化方式有rdb,aof,或者混搭,如果宕机,这个时候还未持久化到硬盘上,会有数据丢失)
  3. 频繁持久化会增大服务器压力,从而降低了redis性能

Redis单线程理解

redis客户端对服务端的每次调用,都经历了:发送命令、执行命令、返回结果,这3个过程。

其中执行命令阶段,由于redis是单线程来处理命令的,所有到达服务端的命令都不会立刻执行,而是先进入一个队列中逐个执行。多个客户端发送的命令执行顺序是不确定的,但可以确定两条命令不会被同时执行,所以不会产生并发问题。这就是redis的单线程基本模型。

redis单线程为什么快?

由于纯内存操作,所以速度非常快

采用单线程的优点,避免了不必要的上下文切换和竞争条件,不用考虑多线程切换以及锁问题。所以没有线程安全问题。

这样会导致无法发挥多核cpu性能,不过可以通过在单机开多个redis实例来提高cpu使用率

I/O多路复用

https://blog.csdn.net/happy_wu/article/details/80052617

多个socket复用同一个I/O

Redis回收策略

当Redis内存已满时,由于内存大小固定,如果继续往里添加数据,就需要淘汰一部分老的数据,释放内存空间来存储新的数据

https://blog.csdn.net/zzl429556205/article/details/103246234

Redis持久化策略

https://blog.csdn.net/zzl429556205/article/details/103246915

原子性

原子性指的是,一个事务是一个不可分割的最小工作单位,要么都成功,要么都失败

Redis的所有单个命令的执行都是原子性的

redis实现事务原理

  1. 批量操作在发送EXEC命令前被放入队列缓存
  2. 收到EXEC命令后进入事务执行,事务中任意命令执行失败,其余的命令都不会被执行
  3. 在事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令序列中

Java实现对redis操作

Jedis

Jedis是Redis官放推荐的面向java的操作Redis客户端。

RedisTemplate

RedisTemplate是SpringDataRedis中对JedisApi的高度封装。SpringDataRedis相对于Jedis可以方便的更换Redis的java客户端,比Jedis多了自动管理链接池的特性。方便与SpringCache搭配使用。

使用RedisTemplate需要进行序列化,方式有:

  • GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
  • Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
  • JacksonJsonRedisSerializer: 序列化object对象为json字符串
  • JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口,不易读)
  • StringRedisSerializer: 简单的字符串序列化

https://blog.csdn.net/hotdust/article/details/51832926

RedisTemplate默认使用JDK序列化(存储复杂类型对象)

StringRedisTemplate使用的是String序列化(存储的是字符串类型数据使用)

JedisPool

JedisPool是一个线程安全的网络连接池,可以创建和管理Jedis实例,降低了开启、关闭连接的开销。

原文:https://www.cnblogs.com/niceyoo/p/10826450.html

序列化

序列化:把对象转换为可传输的子节序列

反序列化:把子节序列还原为对象的过程

为什么需要序列化?

序列化的最终目的是为了对象可以跨平台存储和进行网络传输。

当你使用redis设置key/value时,value对于redis来讲就是一个byte array

Redis失效时间原理

Redis对存储值的过期处理实际上是针对key的处理。

  • 消极方法:每次访问key时判断key是否过器
  • 积极方法:周期性的从设置了过期时间的key中选择一部分的key进行删除(随机测试20个带有失效时间的key,如果超过25%的key被删除,则重复整个流程)

不设置过期时间,就是永久key

可以通过 expire key time来设置过期时间,setNx(key, time, value)是字符串独有的设置失效时间方式

获取key列表

keys命令,遍历方式复杂度是O(n),由于redis是单线程,keys是以阻塞的方式执行的。阻塞时间会过长(keys abc*)

scan命令,是以非阻塞方式进行key值的查找。(scan是一个基于游标的迭代器,每次调用都要需要上一次返回的游标作为参数)

缓存雪崩

缓存同一时间大面积失效,这个时候来了一波请求,导致数据库压力急增,可能会导致数据库连接异常

解决方案:

给缓存失效时间加上随机值,避免集体失效

缓存击穿

故意请求缓存中不存在的数据,导致数据库压力增加

解决方案:

第一次请求无数据,则设置一个短时间失效的缓存,返回空值。再次访问,将不查询数据库,直接返回空值。

管道机制

可以将多次IO往返的时间缩减为一次(将多个命令一次性发送都redis服务端进行处理)

主从/哨兵/集群

主从复制备份了数据,可以做读写分离

哨兵模式,主要提供了redis高可用,master宕机后,会进行选取某个slave提升为master,继续提供服务

集群,主要为了解决redis内存不足时,怎么去扩展内存。使用cluster进行分片存储。

Redis连接异常

对于连接异常,为保证后续任务继续执行,需要在cache中,执行查库操作

try{
redis操作
}catch(redis连接异常){
//请求mysql拿数据
}

Redis事务

Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。

redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

缓存对比

缓存技术数据类型类型持久化
redis丰富(8种)内存数据库,nosqlaof,rdb,混搭
memcached文本内存数据库,key-value不支持

话外

sql层面的缓存几乎没有价值(mybatis二级缓存),所以缓存是基于业务。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值