懒 Redis 是更好的 Redis

  • 时间:
  • 浏览:1
  • 来源:大发11选5_大发11选5官网

然而前阵子我提交了三个多多那先 的什么的问题,在那先 的什么的问题里我承诺提供三个多多一些人(包括我另一方)都你要的功能,叫做“免费懒加载”。原始的那先 的什么的问题在这

这听起来很合理,或者同去即便用快速操作创建的对象有利于否了被删除。在一种状况下,Redis 会阻塞。

好在经过一段尝试已经 ,我找到一种可不都可不还可不可以工作的很好的土法律方式。定时器函数里使用了三个多多想法来适应内存的压力:

第一次尝试

当然,主应用应用程序和延迟释放到程直接对内存分配器的使用肯定会有竞争,不过 Redis 在内存分配上只用到一小帕累托图时间,更多的时间用在I/O、命令埋点、缓存失败等等。

不本来延迟释放

不可能 你现在就想尝试话语,可不都可不还可不可以从Github上下载lazyfree分支。不过要注意的是,当前我并后该很频繁的更新一种分支,一些一些地方不可能 会可不都可不还可不可以了工作。

不可能 慢慢的在后台去删除myset,同去SADD调用又在不断的加带少许的元素,内存使用量不可能 老要增长。

对于单应用应用程序服务器,为了让操作不阻塞,最简单的土法律方式本来用增量的土法律方式一些点来,而后该一下子把整个世界都拿下。之类 ,不可能 要释放三个多多百万级的对象,可不都可不还可不可以每三个多多毫秒释放4000个元素,而后该在三个多多 for() 循环里一次性全做完。CPU 的耗时是差越多的,你爱不爱我会稍微多一些,不可能 逻辑更多一些,或者从用户来看延时更少一些。当然你爱不爱我实际上并那末每毫秒删除4000个元素,这本来个例子。重点是如可防止秒级的阻塞。在 Redis 内部做了一些事情:最显然易见的是 LRU 淘汰机制和 key 的过期,还有一些方面的,之类 增量式的对 hash 表进行重排。

那先 的什么的问题的根本在于,Redis 的 DEL 操作通常是阻塞的。或者不可能 你发送 Redis “DEL mykey” 命令,碰巧你的 key 有 40000万个对象,那末服务器不可能 阻塞几秒钟,在此期间服务器无需防止一些请求。历史上这被当做 Redis 设计的副作用而被接受,或者在特定的用例下这是三个多多局限。DEL 后该唯一的阻塞式命令,却是特殊的三个多多命令,不可能 我们都都都认为:Redis 非常快,我希望你用简化度为 O(1) 和 O(log_N) 的命令。你要自由使用 O(N) 的命令,或者要知道这后该我们都都都优化的用例,你可不都可不还可不可以了做好延迟的准备。

或者,嘿,还可不都可不还可不可以了再多说一句的是,不可能 在 SUNIONSTORE 命令已经 重新加载了数据库,对象都退还了共享,内存也会老要回复到最初的状况。这可不太妙。接下来我们都都都发送应答请求给客户端,会为社 样?当对象比较小时,我们都都都实际上是把它们拼接成线性的缓存,要不然进行多次 write() 调用下行速率 是不高的!(夫妻夫妻感情提示,writev() 并那末帮助)。于是我们都都都大帕累托图状况下是不可能 好友克隆了数据。对于编程来说,那末用的东西却处在,通常原应 是有那先 的什么的问题的。

我在内部增加了一些东西,明天就上线看上去是不现实的。我的计划是先让3.2版(不可能 是unstable状况)成为候选版本(RC)状况,或者把我们都都都的分支合并到进入unstable的3.4版本。

开使英语 英语 我们都都都是那末 尝试的:创建三个多多新的定时器函数,在上边实现淘汰机制。对象本来被加带到三个多多链表里,每次定时器调用的已经 ,会逐步的、增量式的去释放。这可不都可不还可不可以了一些小技巧,之类 ,那先 用哈希表实现的对象,会使用 Redis 的 SCAN 命令里相同的机制去增量式的释放:在字典里设置三个多多游标来遍历和释放元素。通过一种土法律方式,在每次定时器调用的已经 我们都都都可不都可不还可不可以了了释放整个哈希表。在重新进入定时器函数时,游标可不都可不还可不可以不知道们上次释放到 哪里了。

我们都都都也实现了 FLUSHALL/FLUSHDB 的非阻塞版本,不过那末新增的 API,本来增加了三个多多 LAZY 选项,说明算是更改命令的行为。

这里有一小段代码,不过一种想法现在不可能 不再实现了:

事实上,访问三个多多带有聚合类型数据的key,可不都可不还可不可以了经过下面那先 遍历过程:

我们都都都都知道 Redis 是单应用应用程序的。真正的内行会告诉你,实际上 Redis 并后该全版单应用应用程序,不可能 在执行磁盘上的特定慢操作后该有多应用应用程序。目前为止多应用应用程序操作绝大帕累托图集中在 I/O 上以至于在不同应用应用程序执行异步任务的小型库被称为 bio.c: 也本来 Background I/O。

不过在合并已经 ,可不都可不还可不可以了对下行速率 做细致的回归测试,这有不少工作要做。

适配是困难的

不过 API 又为社 样了呢?DEL 命令仍然是阻塞的,默认还跟已经 一样,不可能 在 Redis 中 DEL 命令就原应 释放内存,我无须打算改变一种点。一些现在你要用新的命令 UNLINK,一种命令更清晰的表明了数据的状况。

https://github.com/antirez/redis/issues/1748

这是三个多多小技巧,工作的也很好。不过心烦的是我们都都都还是不得什么都那末单应用应用程序里执行。要做好可不都可不还可不可以了有一些的逻辑,或者当延迟释放(lazy free)周期很繁忙的已经 ,每秒能完成的操作会降到平时的65%左右。

不可能 是在那末 应用应用程序去释放对象,那就简单多了:不可能 三个多多应用应用程序只做释放操作话语,释放老要要比在数据集里加带数据来的要快。

结果是 Redis 现在在内存使用上更加高效,不可能 在数据价值形式的实现上不再使用 robj 价值形式体(不过不可能 一些代码还涉及到少许的共享,一些 robj 依然处在,之类 在命令埋点和好友克隆帕累托图)。应用应用程序化的延迟释放工作的很好,比增量的土法律方式更能减少内存的使用,真是增量土法律方式在实现上与应用应用程序化的土法律方式之类 ,或者也没那末糟糕。现在,你要删除三个多多巨大的 key,性能损失可不都可不还可不可以忽略不计,这非常有用。不过,最有趣的事情是,在我测过的一些操作上,Redis 现在后该变快一些。消除间接引用(Less indirection)最后胜出,即使在不相关的一些测试上也变快一些,还是不可能 客户端的输出缓存现在更加简单和高效。

关于 API 的一些备注

最后,我把增量式的延迟释放实现从分支里删除,只保留了应用应用程序化的实现。

计划表

所有那先 需求起了更激烈的内部变化,但这里的底线我们都都都已很少顾忌。我们都都都可不都可不还可不可以补偿对象好友克隆时间来减少高速缓存的缺失,以更小的内存占用聚合数据类型,一些我们都都都现在可依照应用应用程序化的 Redis 来进行无共享化设计,一种设计,可不都可不还可不可以很容易超越我们都都都的单应用应用程序。在过去,三个多多应用应用程序化的 Redis 看起来总像是三个多多坏主意,不可能 为了实现并发访问数据价值形式和对象其必定是一组互斥锁,但幸运的是还有别的选用 获得这三个多多环境的优势。不可能 我们都都都你要,我们都都都依然可不都可不还可不可以选用 快速操作服务,就像我们都都都过去在主应用应用程序所做的那样。这带有在简化的代价之上,获取执行智能(performance-wise)。

你知道这里最困难的帕累托图是哪里吗?这次我们都都都是在增量式的做一件很有点痛 的事情:释放内存。不可能 内存的释放是增量式的,服务器的内容增长不可能 非常快,最后为了得到更少的延时,会消耗调无限的内存。这很糟,想象一下,有下面的操作:

不可能 加带整个 tobj 价值形式体,把聚合类型转加带 SDS 字符串类型的哈希表(不可能 跳表)会为社 样?(SDS是Redis内部使用的字符串类型)。

那末 做有个那先 的什么的问题,假设有个命令:SADD myset myvalue,举个例子来说,我们都都都做可不都可不还可不可以了通过client->argv[2] 来引用用来实现集合的哈希表的某个元素。我们都都都不得不一些次的把值好友克隆出来,即使数据不可能 在客户端命令解析后创建的参数 vector 里,也没土法律方式去复用。Redis的性能受控于缓存失效,我们都都都你爱不爱我可不都可不还可不可以用稍微间接一些的土法律方式来弥补一下。

于是我在一种 lazyfree 的分支上开使英语 了一项工作,或者在 Twitter 上聊了一下,或者那末提前大选上下文的细节,结果所有的人都真是我像是绝望不可能 疯狂了(甚至许多人喊道 lazyfree 到底是那先 玩意)。那末,我到底做了那先 呢?

不过,要实现应用应用程序化的延迟释放三个多多大那先 的什么的问题,那本来 Redis 自身。内部实现完后该追求对象的共享,最终后该些引用计数。干嘛不尽不可能 的共享呢?那末 可不都可不还可不可以节省内存和时间。之类 :SUNIONSTORE 命令最后得到的是目标集合的共享对象。之类 的,客户端的输出缓存带有了作为返回结果发送给socket的对象的列表,于是在之类 SMEMBERS 那末 的命令调用已经 ,集合的所有成员后该不可能 最终在输出缓存里被共享。看上去对象共享是那末有效、漂亮、精彩,还有点痛 酷。

现在聚合数据类型的值后该再共享了,客户端的输出缓存本来再带有共享对象了,一种点有一些文章可做。之类 ,现在终于可不都可不还可不可以在 Redis 里实现应用应用程序化的 I/O,从而不同的客户端可不都可不还可不可以由不同的应用应用程序去服务。也本来说,可不都可不还可不可以了访问数据库有利于否了全局的锁,客户端的读写系统调用,甚至是客户端发送的命令的解析,都可不都可不还可不可以在应用应用程序中去防止。这跟 memcached 的设计理念之类 ,我比较期待有利于被实现和测试。

还有,现在有利于否在一些应用应用程序实现针对聚合数据类型的特定的慢操作,可不都可不还可不可以让一些 key 被“阻塞”,或者所有一些的客户端无需被阻塞。一种可不都可不还可不可以用很之类 现在的阻塞操作的土法律方式去完成(参考blocking.c),本来增加三个多多哈希表保存那先 正在防止的 key 和对应的客户端。于是三个多多客户端请求之类 SMEMBERS 那末 的命令,不可能 本来仅仅阻塞住这三个多多 key,之前 该创建输出缓存防止数据,已经 在释放一种 key。可不都可不还可不可以了那先 尝试访问相同的 key 的客户端,才会在一种 key 被阻塞的已经 被阻塞住。

UNLINK 是三个多多聪明的命令:它会计算释放对象的开销,不可能 开销很小,就会直接按 DEL 做的那样立即释放对象,或者对象会被放到 后台队列里进行防止。除此之外,这三个多多命令在语义上是相同的。

文章转载自 开源中国社区[https://www.oschina.net]