Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of redis transaction

2025-04-06 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

This article will explain in detail the example analysis of redis transactions for you. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.

One: actual combat of affairs

Specific to what the transaction is and what to guarantee. I don't think it's necessary to say this. Regardless of three, seven and twenty-one, take a look at the redis manual and appreciate its magic.

1. Multi,exec

Do you remember how sqlserver plays? There are usually three steps to generate a transaction, generate a command, and execute a transaction, right? what about the corresponding redis? Multi is to generate a transaction, then enter the redis command, and finally execute the command with exec, like this:

As you can see, after I set the commands, the feedback message is QUEUED, and finally I execute exec, and these commands will really be executed. It is so simple. Everything is executed smoothly and without any muddling. Some people may say that there is actually a rollback operation in the transaction, but I don't seem to see it in redis. Unfortunately, there is no rollback operation in redis, such as the following.

In the figure, I deliberately use the lpush command to execute string, and it is conceivable that it will not succeed, but what do you see from the result? Two OK and one Error is a violation of the atomicity of the transaction, but how can I refute it? Reids is just a data structure server, what a simple thing, to say the least, it will return directly with obvious error commands, such as I deliberately wrote lpush as lpush2:

2. Watch

I don't know if you have a feeling of guilt after reading the three set commands behind multi. How to put it, that is, as long as the command is correct, redis promises to complete the task to the death. Although the command is executed together, who can guarantee that other client will not change these values during the execution of the command? If you change these values, what's the point of my exec? It doesn't matter, how can redis stand idly by the demand of this kind of rotten street? The watch here can help you.

WATCHWATCH key [key...]

Monitor one (or more) key, and if the key (or these) is altered by other commands before the transaction is executed, the transaction will be interrupted.

The above is the explanation of watch in the redis manual. It seems easy to use, that is, I use watch to monitor the key I want to modify before multi. If key is modified by other client during the period before exec and after multi, then exec will fail and return (nil). It's as simple as that. Let me give you an example:

Second: the exploration of principle

Most of the source code for transaction operations is in the multi.c file in the redis source code. I will briefly analyze it one by one:

1. Multi

In the source code of redis, it goes something like this:

Void multiCommand (redisClient * c) {if (c-> flags & REDIS_MULTI) {addReplyError (c, "MULTI calls can not be nested"); return;} c-> flags | = REDIS_MULTI; addReply (cMagneShared.ok)

From this code, you can see that multi simply opens the REDIS_MULTI state of redisClient to tell the redis client that it has entered transaction mode.

two。 Generate command

In redisClient, there is a multiState command:

Typedef struct redisClient {. MultiState mstate; / * MULTI/EXEC state * /. } redisClient

You can probably see from the comments that this command must have something to do with multi/exec, and then I'm curious to look at the definition of multiState:

Typedef struct multiState {multiCmd * commands; / * Array of MULTI commands * / int count; / * Total number of MULTI commands * / int minreplicas; / * MINREPLICAS for synchronous replication * / time_t minreplicas_timeout; / * MINREPLICAS timeout as unixtime. * /} multiState

From the multiState enumeration, you can see that there is a * command command below. You can see from the comments that it actually points to an array, which is your several commands. There is also a count below, which you can see is the total number of actual commands.

3. Watch

To make it easier to talk about exec later, I'd like to talk about how watch is implemented, which is written in the multi.c source code.

Typedef struct watchedKey {robj * key; redisDb * db;} watchedKey; void watchCommand (redisClient * c) {int j; if (c-> flags & REDIS_MULTI) {addReplyError (c, "WATCH inside MULTI is not allowed"); return;} for (j = 1; j

< c->

Argc; jacks +) watchForKey (c-> argv [j]); addReply (c-MagneShared.ok);} / * Watch for the specified key * / void watchForKey (redisClient * c, robj * key) {list * clients = NULL; listIter li; listNode * ln; watchedKey * wk; / * Check if we are already watching for this key * / listRewind (c-> watched_keys,&li); while ((ln = listNext (& li)) {wk = listNodeValue (ln)) If (wk- > db = = c-> db & & equalStringObjects (key,wk- > key) return; / * Key already watched * /} / * This key is not already watched in this DB. Let's add it * / clients = dictFetchValue (c-> db- > watched_keys,key); if (! clients) {clients = listCreate (); dictAdd (c-> db- > watched_keys,key,clients); incrRefCount (key);} listAddNodeTail (clients,c); / * Add the new key to the list of keys watched by this client * / wk = zmalloc (sizeof (* wk)); wk- > key = key; wk- > db = c-> db; incrRefCount (key) ListAddNodeTail (c-> watched_keys,wk);}

Perhaps the core of this code is:

/ * This key is not already watched in this DB. Let's add it * / clients = dictFetchValue (c-> db- > watched_keys,key)

It is through the dictionary method of dicFetchValue to find the value of the specified key from watched_keys, and this value is a linked list of clients, indicating that people actually want to find all the client about this key, and finally insert this key into the watched_keys dictionary of redisclient, as shown in the following code:

/ * Add the new key to the list of keys watched by this client * / wk = zmalloc (sizeof (* wk)); wk- > key = key; wk- > db = c-> db; incrRefCount (key); listAddNodeTail (c-> watched_keys,wk)

If you have to draw a picture, it's something like this:

Where watched_key is a dictionary structure, and the key of the dictionary is key1,key2 above. Value is a linked list of client, so I know exactly which client is being monitored in a key.

4.exec

There are probably two things done in this command:

Determine whether c-> flags=REDIS_DIRTY_EXEC is open or not, and if so, cancel the transaction discardTransaction (c), that is, the key has been modified by another client.

If there is no modification, then execute the command in comannd [] on the for loop, such as the two pieces of information in the following figure:

This is the end of this article on "sample Analysis of redis transactions". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report