Redis的原理介绍及其使用场景

Redis介绍

Redis 是一种开源(BSD 许可)的内存数据结构存储,用作数据库、缓存、消息代理和流式处理引擎。Redis 提供数据结构,例如字符串、哈希、列表、集、带有范围查询的排序集、位图、超日志、地理空间索引和流。

有时我们称Redis为KV数据库,键值对数据库。可以把Redis内部的存储看作是一个大Map,对Map的操作无非就是取值:get 存值:put ,通过key来操作这个key对应的value,这个value的类型可以多种多样,也就是开始提到的字符串,哈希(Hash),列表(List),集(Set)

因为和mysql不同,redis是基于内存的,所以它的读写速度非常惊人,Redis是基于内存存储实现的数据库,相对于数据存在磁盘的数据库,就省去磁盘磁盘I/O的消耗。MySQL等磁盘数据库,需要建立索引来加快查询效率,而Redis数据存放在内存,直接操作内存,所以就很快。

但是可能会有疑问,既然是基于内存,那么如果服务器宕机,停电了,内存不就挂了吗?不过不必担心,Redis可以将内存的数据利用日志快照的形式保存在电脑硬盘,这个样即使遇到突发状况,也不用担心数据丢失。

Redis事务

Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。 总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

官方文档:Introduction to Redis | Redis

为什么要用Redis

减缓数据库压力,Redis作为缓存数据库,可以将数据库中经常需要查询的数据,提前查询,并存储到redis中,当下次需要数据的时候,直接从redis中取值即可,不需要再与数据库进行交互,既减轻了数据库压力,又提升了效率。

1、内存数据库,快,很快.......

2、工作单线程worker,串行化、原子操作. (IO线程是多线程)

3、IO模型(epoll), 支撑高并发.

4、kv模型,v具有类型结构.

5、具有本地方法,计算向数据移动。(a,b) => 交集

二进制安全,Value最大512M

Redis单线程问题

主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。

但Redis的其他功能,比如持久化、异步删除、集群数据同步等等,其实是由额外的线程执行的。Redis工作线程是单线程的,但是,整个Redis来说,是多线程的。

2 Redis单线程为什么快

(1) 基于内存操作:Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的,所以他的性能比较高;

(2) 数据结构简单:Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是 O(1),因此性能比较高;

(3) 多路复用和非阻塞 I/O:Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作;

(4) 避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生;

(5) I/O 多路复用

这是IO模型的一种,即经典的Reactor设计模式,

I/O 多路复用,简单来说就是通过监测文件的读写事件再通知线程执行相关操作,保证 Redis 的非阻塞 I/O 能够顺利执行完成的机制。

多路指的是多个socket连接,

复用指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll。

epoll是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量。

Redis的使用场景

减缓数据库压力

当某个接口查询操作比较频繁,并且数据变化频率不高,那么就可以使用redis来进行缓存数据,进而减轻数据库的压力,当数据库中有增删改操作时就对redis数据进行更新。这样做的目的是为了减缓数据库查询压力。

不同数据类型的使用场景

String

二进制安全:String 类型的值可以包含任何数据,例如 jpg 图片或者序列化的对象,因为Redis不会对字符串类型的值做任何解析,而是将其看作是一个字节数组;

最大容量:Redis 的 String 类型的值最大可以存储 512MB 的内容;

原子操作:Redis 的很多操作都是原子的,也就是说,这些操作要么全部执行,要么全部不执行,不会出现部分执行的情况。这对于并发环境下的操作是非常有用的;

整数和浮点数操作:Redis 提供了一些操作,可以将字符串解析为整数或者浮点数,并执行自增或者自减操作

使用场景

缓存功能

  1. 对于比较费时的、访问比较频繁的查询接口,可以将数据缓存到Redis
    • 计数器
    • 视频播放次数。
    • 全局ID

共享session

  1. 实现分布式session。
  2. 限速
  3. 限制用户访问接口次数。
  4. 限制短信等需要付费的接口的频率:比如通过短信验证码登录。

hash(哈希)

Hash是一个String类型的field和value之间的映射表,即Redis的hash数据类型key(hash表名称)对应的value实际的内部存储结构为一个HashMap。

使用场景

用一个对象来存储用户信息,商品信息,订单信息等等。

key=JavaUser293847
value={
"id": 1,
"name": "商品名称",
"age": 22,
"location": "Wuhan, Hubei"
}

list(列表)

简介

list 就是链表,Redis list 的实现为一个双向链表。可以对列表两端插入(pubsh)和弹出(pop),还可以获取指定范围的元素 列表、获取指定索引下表的元素等,列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,

key=sss
value={ hah, sonw, wek}

使用场景

用户的url权限

  1. 将一个用户拥有的所有url权限存到Redis。
    1. 缓存请求的数据支持高并发
    2. 对于并发量高的接口,可以先将数据缓存到Redis(List结构),后期可以通过定时任务之类的进行异步处理与落库
    3. 组合成其他数据结构
  2.        lpush+lpop=Stack(栈)
    1. lpush+rpop=Queue(队列)
    2. lpush+ltrim=Capped Collection(有限集合)
    3. lpush+brpop=Message Queue(消息阻塞队列)

set(集合)

简介

与列表类似,不同的是集合中不允许有重复的元素。

  • Set内部用HashMap实的,只用了HashMap的key列来存储对象。
  • Set中的元素是无序的,不能通过索引下标获取元素。
  • Set支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。
  • Set是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
  • Set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

使用场景

  • sadd=tagging(标签)
  • 标签(tag):如一个用户对娱乐、体育感兴趣,另一个对新闻感兴趣,这些兴趣就是标签,可获得共同爱好(取交集)的标签(用户和标签的关系维护应该放在一个事物内执行,防止部分命令失败造成数据不一致)
  • spop/srandmember=random item(生成随机数,比如抽奖)
  • sadd+sinter=social Graph(社交需求)
  • sinterstore key1 key2 key3 (求交集,将交集存在key1内)

Key和value的注意事项 

Redis中没有库表这一概念,只有key和value,对于key的构建,一般需要满足以下条件

1:key不可以重复

2:以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id

3:根据key可以知道键值的生成时间,保证key可读性和可管理性

4:保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视

5:【建议】控制key的生命周期,redis不是垃圾桶,键如果不设置过期时间,会一直在内存中,随着时间增长,键占用空间会越来愈大

存取接口的规划:

1、数据结构:Redis 支持多种数据结构,例如字符串、哈希表、列表、有序集合等。根据实际需求选择合适的数据结构,并在接口中定义相应的方法。

2、Key 命名规范:Redis 的 Key 是存储和获取数据的关键,需要定义合适的 Key 命名规范。通常建议使用一定的前缀作为命名空间(时间戳+用户id),避免 Key 冲突。

3、缓存过期策略:如果使用 Redis 作为缓存,需要考虑合适的缓存过期策略,以避免缓存过期后仍然返回旧数据。可以在接口中定义缓存过期时间,并在写入数据时设置过期时间。

4、错误处理:Redis 操作可能会出现网络错误、连接超时等异常情况。在接口中需要定义合适的错误处理机制,例如重试机制、异常捕获等。

5、序列化与反序列化:Redis 存储的数据必须是可序列化的对象。在接口中需要定义合适的序列化与反序列化方式,以便将 Java 对象转换为 Redis 存储格式,并从 Redis 中读取数据并转换为 Java 对象。

6、性能优化:Redis 是一个高性能的内存数据库,但在使用时仍需考虑性能问题。在接口中可以定义一些性能优化策略,例如批量操作、连接池等。

如果想快速在SpringBoot项目中使用Redis请看往期博客:

 SpringBoot项目快速集成Redis-CSDN博客

本期内容分享到这里,感谢观看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值