您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    硬核干货!7600字带你学会 Redis 功用优化点
    时间:2020-05-08 21:07 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    行将开播:5月14日,Jenkins在K8S下的三种部署流程和实战演示

    硬核干货!7600字带你学会 Redis 功用优化点

    在一些网络效劳的系统中,Redis 的功用,能够是比 MySQL 等硬盘数据库的功用更重要的课题。比如微博,把热点微博[1],最新的用户关系,都存储在 Redis 中,少量的查询击中 Redis,而不走 MySQL。

    那么,针对 Redis 效劳,我们能做哪些功用优化呢?或许说,应该避免哪些功用糜费呢?

    Redis 功用的基本面

    在讨论优化之前,我们需求知道,Redis 效劳本身就有一些特性,比如单线程运转。除非修正 Redis 的源代码,不然这些特性,就是我们思索功用优化的基本面。

    那么,有哪些 Redis 基本特性需求我们思索呢?Redis 的项目引见中概括了它特性:

    Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported.

    首先,Redis 运用操作系统提供的虚拟内存来存储数据。而且,这个操作系统普通就是指 Unix。Windows 上也能运转 Redis,但是需求特殊处置。假设你的操作系统运用交流空间,那么 Redis 的数据能够会被实践保存在硬盘上。

    其次,Redis 支持耐久化,可以把数据保存在硬盘上。很多时分,我们也确实有必要停止耐久化来完成备份,数据恢复等需求。但耐久化不会凭空发作,它也会占用一部分资源。

    第三,Redis 是用 key-value 的方式来读写的,而 value 中又可以是很多不同种类的数据;更进一步,一个数据类型的底层还有被存储为不同的结构。不同的存储结构决议了数据增删改查的复杂度以及功用开支。

    最后,在下面的引见中没有提到的是,Redis 大少数时分是单线程运转[2]的(single-threaded),即同一时间只占用一个 CPU,只能有一个指令在运转,并行读写是不存在的。很多操作带来的延迟成绩,都可以在这里找到答案。

    关于最后这个特性,为什么 Redis 是单线程的,却能有很好的功用(依据 Amdahl’s Law,优化耗时占比大的进程,才更有意义),两句话概括是:Redis 应用了多路 I/O 复用机制[3],处置客户端央求时,不会阻塞主线程;Redis 单纯执行(大少数指令)一个指令不到 1 微秒[4],如此,单核 CPU 一秒就能处置 1 百万个指令(大约对应着几十万个央求吧),用不着完成多线程(网络才是瓶颈[5])。

    优化网络延时

    Redis 的官方博客在几个中央都说,功用瓶颈更能够是网络[6],那么我们如何优化网络上的延时呢?

    首先,假设你们运用单机部署(运用效劳和 Redis 在同一台机器上)的话,运用 Unix 进程间通讯来央求 Redis 效劳,速度比 localhost 局域网(学名 loopback)更快。官方文档[7]是这么说的,想一想,实际上也应该是这样的。

    但很多公司的业务规模不是单机部署能支撑的,所以还是得用 TCP。

    Redis 客户端和效劳器的通讯普通运用 TCP 长链接。假设客户端发送央求后需求等候 Redis 前往结果再发送下一个指令,客户端和 Redis 的多个央求就构成下面的关系:

    (备注:假设不是你要发送的 key 特别长,一个 TCP 包完全能放下 Redis 指令,所以只画了一个 push 包)

    这样这两次央求中,客户端都需求阅历一段网络传输时间。

    但假设有能够,完全可以运用 multi-key 类的指令来兼并央求,比如两个 GET key可以用MGET key1 key2兼并。这样在实践通讯中,央求数也增加了,延时自然失掉好转。

    假设不能用 multi-key 指令来兼并,比如一个 SET,一个GET无法兼并。怎样办?

    Redis 中有至少这样两个办法能兼并多个指令到一个 request 中,一个是 MULTI/EXEC,一个是 script。前者本来是构建 Redis 事务的办法,但确实可以兼并多个指令为一个 request,它到通讯进程如下。至于 script,最好应用缓存脚本的 sha1 hash key 来调起脚本,这样通讯量更小。

    这样确实更能增加网络传输时间,不是么?但如此以来,就必需要求这个 transaction / script 中触及的 key 在同一个 node 上,所以要酌情思索。

    假设下面的办法我们都思索过了,还是没有办法兼并多个央求,我们还可以思索兼并多个 responses。比如把 2 个回复信息兼并:

    这样,实际上可以省去 1 次回复所用的网络传输时间。这就是 pipeline 做的事情。举个 ruby 客户端运用 pipeline 的例子:

    require 'redis' 

    @redis = Redis.new 

    @redis.pipelined do 

    @redis.get 'key1' 

    @redis.set 'key2' 'some value' 

    end 

    # => [12

    听说,有些言语的客户端,甚至默许就运用 pipeline 来优化延时成绩,比如 node_redis。

    另外,不是恣意多个回复信息都可以放进一个 TCP 包中,假设央求数太多,回复的数据很长(比如 get 一个长字符串),TCP 还是会分包传输,但运用 pipeline,依然可以增加传输次数。

    pipeline 和下面的其他办法都不一样的是,它不具有原子性。所以在 cluster 形状下的集群上,完成 pipeline 比那些原子性的办法更有能够。

    小结一下:

    运用 unix 进程间通讯,假设单机部署

    运用 multi-key 指令兼并多个指令,增加央求数,假设有能够的话

    运用 transaction、script 兼并 requests 以及 responses

    运用 pipeline 兼并 response

    警觉执行时间长的操作 (责任编辑:admin)