Redis --- 概述、线程模型与基本使用

2021-05-31  本文已影响0人  _code_x

什么是redis?

redis简介(Remote dictionary Server 远程字典服务器):

Redis是开源免费的,由C语言编写的,数据存放在内存,并支持持久化的Nosql数据库,是一种内存数据库,所以它读写速度非常快,主要应用在数据缓存方向。Redis 也经常用来做分布式锁,甚至是消息队列。

Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。

ps:缓存数据处理流程

大致流程:

redis具备的基本特征:

redis关于key-value的三大特点:

  1. redis是支持持久化的!我们可以控制数据何时、用何种方式保存到磁盘中,每次重启再次加载该文件,可以完成数据恢复。
  2. redis不单单支持简单的key-value数据类型,同时还可以提供list、set、hash、zset等数据类型的存储
  3. 支持数据的备份。mater-slave模式,即,当下时髦的主从复制读写分离。

应用场景:

redis为什么这么快?

分布式缓存常见的技术选型? Memcache 与 Redis区别
分布式缓存的话,使用的比较多的主要是 Memcached 和 Redis。不过,现在基本没有看过还有项目使用 Memcached 来做缓存,都是直接用 Redis。

Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来,随着 Redis 的发展,大家慢慢都转而使用更加强大的 Redis 了。

分布式缓存主要解决的是单机缓存的容量受服务器限制并且无法保存通用的信息。因为,本地缓存只在当前服务里有效,比如如果你部署了两个相同的服务,他们两者之间的缓存数据是无法共同的。

共同点:

区别:

redis和mongodb区别

MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于二者在内存映射的处理过程,持久化的处理方法不同。MongoDB建议集群部署,更多的考虑到集群方案,Redis更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。

MongoDB 更类似 MySQL,支持字段索引、游标操作,其优势在于查询功能比较强大,擅长查询 JSON 数据,能存储海量数据,但是不支持事务。

MySQL 在大数据量时效率显著下降,MongoDB 更多时候作为关系数据库的一种替代。

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构。

主要区别:

mmap详解链接:http://www.cnblogs.com/techdoc/archive/2010/12/22/1913521.html

(mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件进行操作。
mmap 系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用。 read(),write()等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里, 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后用msync()同步一下, 你所写的内容就保存到文件里了. 不过这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了。)

redis所有数据都是放在内存中的,持久化是使用RDB方式或者aof方式。
mysql:无论数据还是索引都存放在硬盘中。到要使用的时候才交换到内存中。能够处理远超过内存总量的数据。

redis安装与启动

安装redis

去官网下载压缩包:https://redis.io/download 或者通过 redis 官网提供的在线 redis 环境

安装依赖、编译、安装:

1[root@instance-lynj0v9k-19 redis-5.0.9]# yum install gcc-c++
2[root@instance-lynj0v9k-19 redis-5.0.9]# make
3[root@instance-lynj0v9k-19 redis-5.0.9]# make install

我们自己安装的程序默认都在 /usr/local/bin目录下

启动redis

将redis的配置文件拷贝到/usr/local/bin目录下,之后使用这个配置文件启动。

修改配置文件,让redis后台启动。

1daemonize no # 修改成 yes

指定配置文件,启动redis。

1redis-server /绝对路径/redis.conf

使用redis-client连接redis。

1redis-cli -h 地址 -p 端口号

退出

1# 关闭redis-server
2127.0.0.1:16379> shutdown
3
4# 退出redis-cli
5not connected> exit
6
7# 重新尝试连接,因为redis-server被关闭了,所以会被拒绝
8[root@instance-lynj0v9k-19 bin]# redis-cli -p 16379
9Could not connect to Redis at 127.0.0.1:16379: Connection refused
10not connected> exit
11
12# 查看redis-server是否还在
13[root@instance-lynj0v9k-19 bin]# netstat -luntp | grep 16379
14[root@instance-lynj0v9k-19 bin]#

redis常用基础命令

点击查看所有命令

1# redis默认存在16个数据库,默认一开始使用的是第0个
2[root@instance-lynj0v9k-19 bin]# cat redis.conf | grep  'databases'
3databases 16
4
5# 切换数据库
6127.0.0.1:16379> select 2
7OK
8127.0.0.1:16379[2]>
9
10# 查看数据库容量
11127.0.0.1:16379[2]> DBSIZE
12(integer) 0
13
14# 查看所有的key
15127.0.0.1:16379[2]> keys *
16(empty list or set)
17
18# 清空当前数据库中的值
19127.0.0.1:16379[2]> flushdb
20OK
21
22# 清空所有库
23127.0.0.1:16379[2]> flushall
24OK
数据库的相关命令 指令
关闭redis shutdown
选择数据库(共16个库,默认使用第一个,索引为0) select 库索引
查看当前数据库中key的数量 Dbsize
清空当前库 Flushdb
通杀所有库 Flushall
key常用命令 指令
查看所有key keys *
判断某个key是否存在 exists key
把key移动到别的库 move key db
为key 设定过期时间 expire key 秒钟
查看还有多少秒过期 ttl key
查看当前key是什么类型的 type key

补充问题:为什么用redis?

简单说:提升用户体验和应对更多的用户

下面我们主要从“高性能”和“高并发”这两点来看待这个问题。

高性能 :

对照上面 👆 我画的图。我们设想这样的场景:

假如用户第一次访问数据库中的某些数据的话,这个过程是比较慢,毕竟是从硬盘中读取的。但是,如果说,用户访问的数据属于高频数据并且不会经常改变的话,那么我们就可以很放心地将该用户访问的数据存在缓存中。

这样有什么好处呢? 那就是保证用户下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。

不过,要保持数据库和缓存中的数据的一致性。 如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!

高并发:

一般像 MySQL 这类的数据库的 QPS 大概都在 1w 左右(4 核 8g) ,但是使用 Redis 缓存之后很容易达到 10w+,甚至最高能达到 30w+(就单机 redis 的情况,redis 集群的话会更高)。

ps:QPS(Query Per Second):服务器每秒可以执行的查询次数;

所以,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而,我们也就提高的系统整体的并发。

redis线程模型(单 -> 多线程)

Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型 (Netty 的线程模型也基于 Reactor 模式,Reactor 模式不愧是高性能 IO 的基石),这套事件处理模型对应的是 Redis 中的文件事件处理器(file event handler)。由于文件事件处理器(file event handler)是单线程方式运行的,所以我们一般都说 Redis 是单线程模型。

既然是单线程,那怎么监听大量的客户端连接呢?

《Redis 设计与实现》有一段话是如是介绍文件事件的,我觉得写得挺不错。

文件事件处理器,主要包括四个部分:

虽然说 Redis 是单线程模型,但是,实际上,Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。

不过,Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。

Redis在处理客户端的请求时,包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。但如果严格来讲从Redis4.0之后并不是单线程,除了主线程外,它也有后台线程在处理一些较为缓慢的操作,例如清理脏数据、无用连接的释放、大 key 的删除等等。

大体上来说,Redis 6.0 之前主要还是单线程处理。那,Redis6.0 之前 为什么不使用多线程?

我觉得主要原因有下面 3 个:

Redis6.0 引入多线程主要是为了充分利用cpu资源,提高网络 IO 读写性能,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。

虽然,Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了, 执行命令仍然是单线程顺序执行。因此,你也不需要担心线程安全问题。

# Redis6.0 的多线程默认是禁用的,只使用主线程。如需开启需要修改 redis 配置文件 redis.conf :
io-threads-do-reads yes

# 开启多线程后,还需要设置线程数,否则是不生效的。同样需要修改 redis 配置文件 redis.conf :
io-threads 4 #官网建议4核的机器建议设置为2或3个线程,8核的建议设置为6个线程

ps:Redis6.0与Memcached多线程模型对比

ps:Redis线程中经常提到IO多路复用,如何理解?

拓展:高性能IO模型

服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

拓展:同步、异步和阻塞、非阻塞

拓展:Reactor设计模式

通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。由于select函数是阻塞的,因此多路IO复用模型也被称为异步阻塞IO模型。注意,这里的所说的阻塞是指select函数执行时线程被阻塞,而不是指socket。一般在使用IO多路复用模型时,socket都是设置为NONBLOCK的,不过这并不会产生影响,因为用户发起IO请求时,数据已经到达了,用户线程一定不会被阻塞。

IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因为它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO,而非真正的异步IO。

巨人的肩膀

https://snailclimb.gitee.io/javaguide/#/docs/database/Redis/redis-all

https://mp.weixin.qq.com/s/CMu7oXVIKp2s-PXTdMlimA

https://www.cnblogs.com/yanguhung/p/10145755.html

https://www.jianshu.com/p/2b523fbee36f

上一篇 下一篇

猜你喜欢

热点阅读