目录

  • redis与memcached
  • redis单线程能支持高并发
  • 传统的BIO(blocking IO)
  • NIO
  • redis的reactor设计模式
  • 至于redis的多路复用
  • epoll与poll与select
  • Redis与Zk分布式锁
  • Redis数据类型
  • 五种常用的数据结构


redis与memcached

redis倾向提供更复杂的数据结构,memcache无法提供。
redis自带高可用集群,实现主从读写分离功能,自带哨兵模式。memcache需要二次开发
memcache存储最大只有1M,而redis支持512M
memcache多线程,主线程监控,worker子线程接受请求,在整个过程中,可能存在锁冲突。redis使用单线程,虽无锁冲突,但是没有多核的特性提升吞吐量。
存储问题,memcache没法持久化,redis可以通过Aof

redis单线程能支持高并发

redis实现了多路复用,因为redis单线程,所有的操作都是线性的。但是由于读写操作等待用户输入与输出都是阻塞的。
所以IO一般情况下不能直接返回,导致某一个文件的阻塞导致整个进程无法对其他客户提供服务,而IO多路复用就是为了解决这个问题出现的。

传统的BIO(blocking IO)

当使用 read 或者 write 对某一个文件描述符(File Descriptor 以下简称 FD)进行读写时,如果当前 FD 不可读或不可写,整个 Redis 服务就不会对其它的操作作出响应,导致整个服务不可用

redis 数据库 多进程 redis 多进程 读写_多路复用

NIO

redis 数据库 多进程 redis 多进程 读写_redis 数据库 多进程_02


在多路复用过程最重要的函数就是select,该方法能够同时监控多个文件描述符的可读写情况,当其中的某些文件可读可写,select方法返回可读可写的文件描述个数。与此同时也有其它的 I/O 多路复用函数 epoll/kqueue/evport,它们相比 select 性能更优秀,同时也能支撑更多的服务。

redis的reactor设计模式

redis采用的这种reactor设计模式,每一个fd文件操作符都对应一个网络请求。

redis 数据库 多进程 redis 多进程 读写_分布式锁_03


文件事件处理器使用 I/O 多路复用模块同时监听多个 FD,当 accept、read、write 和 close 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器。虽然整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,提高了网络通信模型的性能,同时也可以保证整个 Redis 服务实现的简单。

至于redis的多路复用

I/O 指的是网络I/O。
多路指的是多个TCP 连接(Socket 或Channel)。
复用指的是复用一个或多个线程。

epoll与poll与select

epoll的设计和实现与select完全不同。epoll通过在Linux内核中申请一个简易的文件系统(文件系统一般用B+树数据结构实现)。把原先的select/poll调用分成了3个部分:

1)调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源)

2)调用epoll_ctl向epoll对象中添加这100万个连接的套接字

3)调用epoll_wait收集发生的事件的连接实现上面场景只需要在进程启动时建立一个epoll对象,在需要的时候向epoll对象中添加或者删除连接。同时epoll_wait的效率也非常高,因为调用epoll_wait时,并没有一股脑的向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接。

Redis与Zk分布式锁

学完了两种分布式锁的实现方案之后,本节需要讨论的是redis和zk的实现方案中各自的优缺点。对于redis的分布式锁而言,它有以下缺点:它获取锁的方式简单粗暴,获取不到锁直接不断尝试获取锁,比较消耗性能。另外来说的话,redis的设计定位决定了它的数据并不是强一致性的,在某些极端情况下,可能会出现问题。锁的模型不够健壮即便使用redlock算法来实现,在某些复杂场景下,也无法保证其实现100%没有问题,关于redlock的讨论可以看How to do distributed lockingredis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能。但是另一方面使用redis实现分布式锁在很多企业中非常常见,而且大部分情况下都不会遇到所谓的“极端复杂场景”所以使用redis作为分布式锁也不失为一种好的方案,最重要的一点是redis的性能很高,可以支撑高并发的获取、释放锁操作。对于zk分布式锁而言:zookeeper天生设计定位就是分布式协调,强一致性。锁的模型健壮、简单易用、适合做分布式锁。如果获取不到锁,只需要添加一个监听器就可以了,不用一直轮询,性能消耗较小。但是zk也有其缺点:如果有较多的客户端频繁的申请加锁、释放锁,对于zk集群的压力会比较大。

Redis数据类型

五种常用的数据结构

这个没什么好说的,对Redis稍微有点了解的都知道5种最基本的数据结构:String,List,Hash,Set,Sorted Set。