c#中用lua脚本执行redis命令

c#中用lua脚本执行redis命令

直接贴出代码,实现执行lua脚本的方法,用到的第三方类库是 StackExchange.Redis(nuget上有)
注:下面的代码是简化后的,实际使用要修改,

 

[csharp] view plain copy
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Threading.Tasks;  
  6. using StackExchange.Redis;  
  7.   
  8.   
  9. namespace TL.Cloud.KV  
  10. {  
  11.     public class Kv:IKv  
  12.     {  
  13.          
  14.          
  15.         private  ConfigurationOptions _redisConfig;// = new ConfigurationOptions  
  16.         private  IDatabaseAsync _db;//=Connection.GetDatabase();  
  17.         private  IServer _server;// = GetServer();  
  18.         private  string _keyPrefix;// 区分前缀  
  19.   
  20.         /// <summary>  
  21.         /// 每个微服务一个kv云实例,或共享云实例中(无独立前缀,服务间Key取名需要自行防止冲突)  
  22.         /// </summary>  
  23.         /// <param name="hostServiceName">宿主微服务</param>  
  24.         public Kv(PublicCloudKvConfig config)  
  25.         {  
  26.             Init(config);  
  27.         }  
  28.   
  29.         private void Init(PublicCloudKvConfig config)  
  30.         {  
  31.             //独特的区分dev/100前缀,online可以没有  
  32.             _keyPrefix = string.IsNullOrWhiteSpace(config.KeyPrefix)  
  33.                 ?null  
  34.                 :config.KeyPrefix.Trim().ToLower()+':';//小写带冒号分割  
  35.             //ali kv  
  36.             var kvUrl = config.KvUrl;  
  37.   
  38.   
  39.             _redisConfig = ConfigurationOptions.Parse(kvUrl);  
  40.              
  41.             _redisConfig.Password = config.KvPassword;  
  42.             _redisConfig.SetDefaultPorts(); //自动填充默认端口  
  43.             var connection = ConnectionMultiplexer.Connect(_redisConfig);  
  44.             _db = connection.GetDatabase();  
  45.             _server = GetServer();  
  46.               
  47.         }  
  48.   
  49.         private  IServer GetServer()  
  50.         {  
  51.             var config = new ConfigurationOptions  
  52.             {  
  53.                 KeepAlive = 0,  
  54.                 EndPoints = { _redisConfig.EndPoints[0]},  
  55.                 AbortOnConnectFail = false,  
  56.                 AllowAdmin = true  
  57.             };  
  58.             var conn = ConnectionMultiplexer.Connect(config);  
  59.             return conn.GetServer(config.EndPoints[0]);  
  60.         }  
  61.   
  62.         public Task<RedisResult> EvalLua(string lua, IList<RedisKey> keys, IList<RedisValue> values)  
  63.         {  
  64.             if (_keyPrefix != null)  
  65.                 keys = keys.Select(p => p.Prepend(_keyPrefix)).ToList();//加上前缀  
  66.             return _db.ScriptEvaluateAsync(lua, keys.ToArray(), values.ToArray());  
  67.         }  
  68.           
  69.   
  70.         public async Task<RedisResult> EvalLua(byte[] luaSha1, IList<RedisKey> keys, IList<RedisValue> values)  
  71.         {  
  72.             if (_keyPrefix != null)  
  73.                 keys = keys.Select(p => p.Prepend(_keyPrefix)).ToList();//加上前缀  
  74.             return await _db.ScriptEvaluateAsync(luaSha1, keys.ToArray(), values.ToArray());  
  75.         }  
  76.           
  77.         
  78.   
  79.         public async Task<byte[]> LoadLuaToServerAsync(string lua)  
  80.         {  
  81.             var sha1 = lua.CalcLuaSha1();//本地计算  
  82.             if(!await _server.ScriptExistsAsync(sha1))//服务器上不存在  
  83.                  sha1 = await _server.ScriptLoadAsync(lua);//应该和计算的相同  
  84.                   
  85.             return sha1;  
  86.         }  
  87.     }  
  88. }  

 

 

下面是测试代码段

 

[csharp] view plain copy
 
  1. //下面是测试代码  
  2.         [Test]  
  3.         public async Task LoadLuaToServerAsync()  
  4.         {  
  5.             var key = "TestEvalLua10010";  
  6.             var fieldContent = "testlua10011";  
  7.             const string lua =  
  8.                 "redis.call('SET', KEYS[1], ARGV[1])\n" +  
  9.                 "return redis.call('GET', KEYS[1])\n";  
  10.   
  11.             var sha2 = lua.CalcLuaSha1();  
  12.             var sha1 = await _kv.LoadLuaToServerAsync(lua);  
  13.             Assert.AreEqual(20, sha1.Length);  
  14.             for (var i = 0; i < 20; i++)  
  15.                 Assert.AreEqual(sha1[i],sha2[i]);  
  16.               
  17.             var keys = new List<RedisKey> { key };  
  18.             var values = new List<RedisValue> { fieldContent };  
  19.             var result = await _kv.EvalLua(sha1, keys, values);  
  20.             Assert.AreEqual(fieldContent, (string)result);  
  21.         }  



计算sha1用到的方法

 

 

[csharp] view plain copy
 
  1. //计算lua的sha1结果,作为执行lua的参数  
  2.         public  static byte[] CalcLuaSha1(this string lua)  
  3.         {  
  4.             SHA1 sha1 = new SHA1CryptoServiceProvider();  
  5.             var bytesSha1In = Encoding.Default.GetBytes(lua);  
  6.             return sha1.ComputeHash(bytesSha1In);  
  7.         }  
posted @ 2017-03-13 15:46  DemiGoo  阅读(311)  评论(0编辑  收藏  举报