单线程的redis如何实现并发访问?

在服务器端软件中, 并发和并行性一般被认为是不一样的概念。在服务器中, 支持并发 i/o 意味着服务器可以经过执行与那些客户端仅有一个计算单元对应的几个流来为多个客户端提供服务。在这种状况下, 并行性意味着服务器可以同时执行多个操做 (具备多个计算单元), 这是不一样的。服务器

例如, 一个酒保能够照顾几个客户, 而他只能准备一次饮料。这样他就能够不并行地提供并发性。网络

单线程程序绝对能够经过使用 i/o 复用机制和事件循环 (Redis用的是事件循环), 在 i/o 级别上提供并发性。并发

并行性具备成本: 在现代硬件上能够找到多个套接字/多个内核, 线程之间的同步很是昂贵。另外一方面, 像 Redis 这样的高效存储引擎的瓶颈每每是网络--CPU前面的陷阱。所以, 孤立的事件循环 (不须要同步) 被视为构建高效、可伸缩的服务器的良好设计。线程

Redis 操做是原子的事实仅仅是单线程事件循环的结果。有趣的一点是, 原子性是以不额外的成本提供的 (它不须要同步)。用户能够利用它来实现乐观锁定和其余模式, 而无需支付同步开销。设计

若是 Redis 是单线程的, 那么为何须要锁定机制呢?code

Redis 确实 (大可能是) 单线程, 但当多个客户端尝试在相邻的时间接近时进行不一样的事情时, 则须要锁定。在 RiA 中讨论的锁定彻底是关于-确保只有一个客户端/线程执行特定任务, 或者确保更新不会出错。事件

这里有一个例子, 为何你须要锁定, 尽管 Redis 有单线程性: 假设你有一个值在 Redis, 一个数字, 例如存储在一个名为 foo 的键值下。您的应用程序的代码读取该数字 (GET foo), 作一些事情 (ADD 1) 并将其写回 (SET)。当您在单个线程中运行代码时, 这就是它的外观:同步

应用程序 Redis服务器端

App               Redis
 |---- GET foo ---->|
 |<------ 1 --------|
 |                  |
 | thinking...      |
 |                  |
 |--- SET foo 2 --->|
 |<----- OK --------|

如今让咱们看看两个应用程序客户端尝试这样作时会发生什么:软件

App 1             Redis              App 2
 |---- GET foo ---->|                  |
 |<------ 1 --------|<--- GET foo -----|
 |                  |------- 1 ------->|
 | thinking...      |                  |
 |                  |       thinking...|
 |--- SET foo 2 --->|                  |
 |<----- OK --------|<--- SET foo 2 ---|
 |                  |------ OK ------->|

在这里你能够当即看到发生了什么,由于没有锁定, 尽管服务器 (主要是) 单线程的-获得的结果不是 3, foo 的值最终是2。当您添加更多的线程/客户/应用程序时, 当多个做者尝试修改数据而不进行协调 (即锁定) 时, 事情会变得更加欢快而严重。

乐观锁定只是一种方法, Redis 经过监视机制提供内置。然而, 有时, 乐观-尽管看上去容易且快乐-一般不是正确的解决方案, 因此你须要实施更好/先进/不一样的机制, 以防止竞态条件。能够说, 这样的锁可能在 Redis 以外实现, 但若是您已经使用它, 那么在其中管理您的锁也是有意义的。

相关文章
相关标签/搜索