【问题标题】:Conditional Redis set / only update with newest version?条件 Redis 设置/仅更新最新版本?
【发布时间】:2014-04-07 18:40:06
【问题描述】:

有没有办法在 Redis 中做条件集?

我想用 Redis 来缓存一些对象。缓存的每个用户(服务器程序)都会检查一个对象,如果它有更新的版本,就更新它。我需要确保在更新步骤中只有最新版本真正保存在 Redis 中。

【问题讨论】:

    标签: redis


    【解决方案1】:

    您可以编写一个 lua 脚本来检查键的当前值并在值与新值不同时更改它。我在 c 中添加了一个通过 c-program 调用 lua 脚本并完成所需工作的示例。

      //g++ -g -o condition condition.cpp  -I/usr/local/include/hiredis -L/usr/local/lib  -levent -lhiredis
    /*----------------------
      EVAL
      ------------------------*/
    
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    #include <hiredis/hiredis.h>
    
    using namespace std;
    
    struct timeval _timeout ;
    redisContext *_redisContext;
    const long long SEC_TO_USEC = 1000000 ;
    
    void connect(const std::string &ip,
        int port,
        int timeoutInUsec )
    {
      _timeout.tv_sec = timeoutInUsec / SEC_TO_USEC ;
      _timeout.tv_usec = timeoutInUsec % SEC_TO_USEC ;
    
      _redisContext = redisConnectWithTimeout(ip.c_str(), port, _timeout);
      if (_redisContext->err)
      {
        std::cout << "Cannot connect to redis server. "
          << " Error : " << _redisContext->errstr
          << std::endl ;
        exit(1);
      }
    }
    
    //lua scrip for conditional set
    string scriptMultipleCommands =
    "local res = redis.call(\"GET\", KEYS[1])              "
    "if res == ARGV[1] then                                "
    " return nil                                           "
    "else                                                  "
    "redis.call(\"SET\", KEYS[1],  ARGV[1])                "
    "end                                                   "
    "local data = redis.call(\"GET\",KEYS[1])              "
    "return data                                           ";
    
    void luaCommand(char** argv)
    {
      string command;
      command.append( scriptMultipleCommands );
      redisReply *reply =
        ( redisReply * ) redisCommand( _redisContext,
            "EVAL %s %d %s %s ",command.c_str(),1,argv[1],argv[2]);
    
      cout<<"Redis reply type "<<reply->type<<endl;
    
      if (reply->type == REDIS_REPLY_ARRAY)
      {
        cout<<"Redis reply size "<<reply->elements<<endl;
        for (int j = 0; j < reply->elements; j++)
        {
          if((j+1) < reply->elements)
          {
            cout<<(reply->element[j]->str)<<","<<(reply->element[j+1]->str)<<endl;
            ++j;
          }
        }
      }
      else if (reply->type == REDIS_REPLY_INTEGER) {
        cout<<"Key value "<<reply->integer<<endl;
      }
      else
        cout<<endl<<"EVAL: "<< reply->str<<endl;
    
      freeReplyObject(reply);
    }
    
    int main(int argc,char** argv)
    {
      connect("10.0.0.30",6379,1500000);
      luaCommand(argv);
    
      return 0;
    }
    

    【讨论】:

    • 脚本是否在 Redis 上原子执行?
    • @edA-qamort-ora-y 是的,脚本的执行将是原子的。阅读 Redis Lua Scripting 的文献,它清楚地提到了这一点;执行特定脚本时不会发生其他事务,类似于 REDIS TRANSACTIONS MULTI/EXEC
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 2020-06-16
    相关资源
    最近更新 更多