redis share performance issues

In some network services in the system, Redis performance, may be more important than the performance of the MySQL database and other hard issues. Such as micro-Bo, the hot microblogging [1], recent relations between the user are stored in Redis, a large number of queries hit Redis, rather than go MySQL.

So, for Redis service, what we can do to optimize the performance of it? Or, what a waste of performance should avoid it?

Redis performance fundamentals

Before discussing optimization, we need to know, Redis service itself has some features, such as single-threaded run. Redis modify the source code unless otherwise these characteristics that we think the fundamentals of performance optimization.

So, what Redis basic characteristics we need to consider it? Redis project presentation outlines its features:

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

1.Redis use virtual memory to store the data provided by the operating system. Moreover, the operating system generally refers to Unix. Windows can run on Redis, but require special handling. If your operating system swap space, then the Redis data may be actually stored on the hard disk.

2.Redis support persistence, data can be stored on the hard disk.

3.Redis key-value is a way to read and write, and the value in turn can be many different types of transactions; Still further, a type of data stored there a different underlying structure. Different determines the data storage structure CRUD complexity and performance overhead.

Most of the time a single thread 4.Redis [2] (single-threaded), i.e. a same time occupies only the CPU, only one operation instruction, concurrent read does not exist.

Finally on this feature, why Redis is single-threaded, but it can have a good performance (according to Amdahl's Law, optimizing large proportion of the time-consuming process, it makes more sense), is summarized in two words: Redis use of multiple I / O multiplexing mechanism [3], when the client request does not block the main thread; Redis a simple instruction execution (most instructions) is less than 1 microsecond [4], thus, one second single-core CPU can instruction processing 1 million (roughly corresponding to hundreds of thousands of requests it), do not need multi-threaded (network is the bottleneck [5]).

Optimize network latency

Redis's official blog said, performance bottlenecks are more likely to be network [6] in several places, so how do we optimize the latency on the network do?

First, if you use the standalone deployment (and Redis application services on the same machine), then,

1. Unix inter-process communication to request Redis service, faster than localhost local area network (scientific name loopback). Official documents [7] says so, think about it, in theory, it should be like this.

But a lot of the company's business scale is not a stand-alone deployment can support, they still have to use TCP.

Redis server and client communications generally use TCP long link. If the client sends a request to return the result needs to wait retransmission Redis next instruction, and a plurality of client requests Redis on a relation of the following:

uploading.4e448015.gifDump failed to re-upload canceled

(Note: key if you want to send is not particularly long, fully able to put down a TCP packet Redis commands, so only drew a push package)

So these two requests, the client needs to go through a period of network transmission time.

However, if possible, can use multi-key command to merge request class, such as GET key can be combined with two MGET key1 key2. So the actual communication, but also reduces the number of requests, the delay naturally get better.

If you can not be merged with the multi-key commands, such as a SET, GET not a merger. How to do?

Redis least two such methods can be incorporated into a plurality of request commands, one is a MULTI / EXEC, is a script. The former method was originally constructed Redis transaction, but it can merge multiple instructions as a request, it follows the communication process. As for the script, the best use cache script sha1 hash key to invoking the script, so traffic is smaller.

uploading.4e448015.gifDump failed to re-upload canceled

So do more to reduce network transmission time, is not it? But so since you must ask this key transaction / script involved on the same node, so to consider, as appropriate.

If the above method we have considered, is no way to merge multiple requests, we can also consider merging multiple responses. For example, the two merge reply:

uploading.4e448015.gifDump failed to re-upload canceled

Thus, in theory, be omitted network transmission time for a reply from the primary. This is the pipeline to do. For clients use a pipeline ruby ​​example:

require 'redis'

@redis = Redis.new ()

@redis.pipelined do

@redis.get 'key1'

@redis.set 'key2' 'some value'

end

# => [1, 2]

It is said that some of the language of the customer end, and even acquiescence on the use of pipeline to optimize latency problems, such as node_redis.

In addition, more than any reply information can be put into a TCP packet, if too many requests, replies the data is very long (for example, get a long string), TCP still sub-transmission, but the use of pipeline, still reduce the number of transmissions.

pipeline and other methods above are not the same, it is not atomic. So on the cluster in the cluster state, to achieve pipeline more than those atomic possible.

Summary about:

  1. Inter-process communication using unix, if the stand-alone deployment
  2. The combined use of a plurality of multi-key command instructions, to reduce the number of requests, if possible,
  3. Use transaction, script merge requests and responses
  4. The combined use of pipeline response

Wary of execution for a long time operation

In the case of a large amount of data, the execution time of some operations may be relatively long, such KEYS *, LRANGE mylist 0 -1, and the other algorithm complexity is O (n) instructions. Because only one thread to do Redis data query, if these directives take a long time, Redis will be blocked, causing a lot of delay.

Although the official documents say KEYS * query very quickly, (on an ordinary laptop) to scan 1 million key, just 40 milliseconds (see: https: //redis.io/commands/keys), but tens of ms for a high performance requirements of the system, it is not short, not to mention if there are hundreds of millions of key (a complete machine may exist hundreds of millions of key, such as a 100-byte key, only key 10GB 100,000,000) and longer.

So, try not to use the slow implementation of the code of instruction in a production environment, the authors of this Redis in the blog [8] are also mentioned. In addition, operation and maintenance queries Redis students, also try not to use. Even, Redis Essential recommend this book use rename-command KEYS '' to prohibit the use of this time-consuming instructions.

In addition to these instructions time-consuming, in Redis transaction, script, since a plurality of commands can be combined to perform a process of atom having Redis it may also take a long time, to be noted.

If you want to find out "slow instruction" production environments, then you can use SLOWLOG GET count to view the most recent count execution time is very long instruction. As long count length may be defined by setting slowlog-log-slower-than in the redis.conf.

In addition, in a possible slow instructions are not many places mentioned DEL, but the comment redis.conf file [9] in'd say. Long story short DEL is a large object when the corresponding memory recovery may take a long time (or even seconds), it is recommended to use the asynchronous version of DEL: UNLINK. The latter will start a new thread to remove the target key, without blocking the original thread.

Further, when a key expires, Redis generally need to delete it synchronized. One way is to delete keys, 10 times per second checked once have set the expiration time of keys, these keys are stored in a global struct, you can use server.db-> expires visit. Check the way is:

  1. Taken randomly from 20 keys
  2. The expired deleted.
  3. If just 20 keys, more than 25% (that is, more than five) are expired, Redis think, pretty much outdated keys, and continue to repeat Step 1 until the exit condition is satisfied: Remove the keys in a particular not so much in the past of keys.

Here is the effect on the performance, if you really have a lot of keys expire at the same time, it really has been circulating Redis delete, occupied the main thread.

In this regard, Redis authors suggested [10] is vigilant EXPIREAT this directive, because it is easier to generate keys are overdue phenomenon. I have also seen some of the recommendations is to set the expiration time keys of a random fluctuation amount. Finally, redis.conf also given a method, the deletion operation becomes expired keys asynchronous, i.e., provided lazyfree-lazy-expire yes in the redis.conf.

Optimized data structures, using the correct algorithm

A data type (such as string, list) for CRUD its efficiency is determined by the underlying storage structure.

When we use a data type, it can be appropriate to look at the storage structure and algorithm underlying it, avoid using too much of the complexity of the method. Here are two examples:

  1. ZADD time complexity is O (log (N)), which a new element of the operation is more complex than other types of data increases, so should be used carefully.
  2. Hash values ​​if a limited number of fields of type, it is likely to adopt this structure do ziplist storage, and query efficiency ziplist may not have the same number of fields hashtable high efficiency, when necessary, adjust the storage structure of Redis.

In addition to considering the performance on time, and sometimes we need to save storage space. Ziplist such as the above-mentioned structure, saving storage space than the structure hashtable (Redis Essentials 500 are inserted into the fields of the hashtable and the Hash ziplist structure, and each field value is about a 15-bit string, the result spatial structure is used four times ziplist the hashtable.). But saving data space, the complexity of the algorithm may be high. So, here we need to make trade-offs in the face of specific problems. Welcome to public concern number: Zhu servant's blog, Re: 1024, redis can receive exclusive information.

How to make better trade-off? I think have to dig deep storage structure Redis is to make their own peace of mind. The content of this field the next time we talk.

These three points are programmed level above considerations, it should be noted that written procedures ah. Below these points, it will also affect the performance of Redis, but to solve them, not just by adjusting the code level, but also need to consider the structure and operation and maintenance.

Consider whether the operating system and hardware performance impact

Redis running the external environment, which is the operating system and hardware obviously also affect the performance of Redis. In an official document, it gives a few examples:

  1. CPU: Intel more good than CPU AMD Opteron Series
  2. Virtualization: physical machine better than the virtual machine, mainly because of the part of the virtual machine, not a local hard disk drive, leading to fork monitoring software instructions slow (fork will be used when persistence), especially when using Xen virtualization do .
  3. Memory management: in linux operating system, in order to allow translation lookaside buffer, ie the TLB, the ability to manage more memory space (TLB cache only a finite number of page), operating system, some memory page becomes larger, such as 2MB or 1GB, instead of the usual 4096 bytes, these large memory pages is called huge pages. At the same time, in order to facilitate the programmer to use these large memory page, the operating system is implemented in a transparent huge pages (THP) mechanism that enables a large memory pages for them is transparent, you can use as they like using normal memory page. But this mechanism is not required for the database, possibly because of THP will be compact and continuous memory space bar, like mongodb documents [11] explicitly said, the database required memory space is sparse, so please ban THP function. Redis is no exception, but the reasons given on the official blog Redis is: when using the large memory page will bgsave, fork slow down; if after the fork, these memory page has been modified in the original process, they need to be copied (ie copy on write), this copy will consume a lot of memory (after all, they are huge pages, a copy of the consumption of large costs). So please, prohibit off transparent huge pages feature in the operating system.
  4. Swap space: When some memory page is in the swap file space, but those requests have to Redis data store, the operating system will block Redis process, and then the desired page, out from the swap space into memory. Which involves blocking the whole process, it may cause a delay problem, a solution is to prohibit the use of swap space (Redis Essentials in the case suggested that if the memory space is insufficient, please use other treatment methods).

Consider the overhead caused by persistent

An important feature Redis is persistent, that is, to copy data to the hard disk. Based on persistence, only the Redis data recovery functions.

But to maintain this persistent feature is also a performance overhead.

First of all that, RDB full amount of persistence.

This way the total amount of persistent data Redis rdb is packaged into files on the hard disk. However, the implementation process RDB persistence of the original process fork out a child process, while the fork system call takes time, based on the experimental Redis Lab 6 years ago to do [12], in a new AWS EC2 m1.small ^ on 13, fork a 1GB memory footprint Redis process, requiring 700 + ms, but this time, redis is unable to process the request.

Although the machine will be better than at that time, but the fork should also consider the cost of it. To do this, use reasonable RDB persistent intervals, not too frequent.

Next, we look at another persistent way: AOF incremental persistence.

This persistent way to redis server will send you instructions stored in the form of text down (format follows the redis protocol), the process, the system will call the two calls, one is the write (2), the synchronization is complete, one is fsync (2), asynchronous completion.

These two issues are likely to be the cause of the delay:

  1. write may be because the output buffer is full, or kernal is the data buffer is synchronized to the hard disk, it was blocked.
  2. Fsync role is to ensure that the data written to the write fell aof file on the hard disk, in a 7200 / min hard disk may be a delay of about 20 milliseconds, or big consumption. More importantly, when fsync done, write may be blocked.

Which, write seemingly blocking can only accept, because there is no better way to write data to a file in the. But for fsync, Redis allows three configurations, depending on what kind of backup you balance timeliness and performance selection:

  1. always: When appendfsync set to always, fsync will synchronize execution and the client's instructions, so the most likely cause delay problem, but the backup timeliness of the best.
  2. everysec: once per second asynchronous execution fsync, this time redis performance will be better, but still fsync may block write, be regarded as a compromise choice.
  3. no: redis will not take the initiative to start fsync (not always without fsync, it is unlikely), determined by the kernel when fsync

Using a distributed architecture - separate read and write data partitioning

Above, we are based on a single, or a single Redis service optimization. Now, when we consider the size of the site increases, the use of a distributed architecture to security issues Redis performance.

First of all that, under what circumstances have to (or better) using a distributed architecture:

  1. Large amounts of data, a single server can not be installed under the memory, such that the order of 1 T
  2. Require high availability service
  3. Request single excessive pressure

These data can be used to solve problems or fragment is separated from the master, or both are used (i.e., fragments on cluster nodes use, be provided from a master structure).

Such a framework can add a new entry point for performance improvement:

  1. The slow execution instruction sent from the library to a certain
  2. The persistence function on a little-used from the library on
  3. The list of some big fragments

Of which the first two are based on the characteristics of the Redis single-threaded, so the performance of complementary approach with other processes (even machine).

Of course, using a distributed architecture, may also affect performance, such as the request needs to be forwarded, copied data needs to be continuously distributed. (Of unknown origin)

After words

In fact, there are many things also affect performance Redis, such as active rehashing (re-hash keys of the main table, 10 times per second, turn it off a little bit can improve performance), but this blog has written very long. Moreover, the problem is more important than the collection have been proposed by others, and memory solutions; but Redis master the basic principles, the question of maintaining the status quo way to pull off emerging.

Source: ZHU Xiao-off Seeb

Published 277 original articles · won praise 65 · views 380 000 +

Guess you like

Origin blog.csdn.net/ailiandeziwei/article/details/104776084