c#中用lua脚本执行redis命令
c#中用lua脚本执行redis命令
直接贴出代码,实现执行lua脚本的方法,用到的第三方类库是 StackExchange.Redis(nuget上有)
注:下面的代码是简化后的,实际使用要修改,
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Threading.Tasks;
- using StackExchange.Redis;
- namespace TL.Cloud.KV
- {
- public class Kv:IKv
- {
- private ConfigurationOptions _redisConfig;// = new ConfigurationOptions
- private IDatabaseAsync _db;//=Connection.GetDatabase();
- private IServer _server;// = GetServer();
- private string _keyPrefix;// 区分前缀
- /// <summary>
- /// 每个微服务一个kv云实例,或共享云实例中(无独立前缀,服务间Key取名需要自行防止冲突)
- /// </summary>
- /// <param name="hostServiceName">宿主微服务</param>
- public Kv(PublicCloudKvConfig config)
- {
- Init(config);
- }
- private void Init(PublicCloudKvConfig config)
- {
- //独特的区分dev/100前缀,online可以没有
- _keyPrefix = string.IsNullOrWhiteSpace(config.KeyPrefix)
- ?null
- :config.KeyPrefix.Trim().ToLower()+':';//小写带冒号分割
- //ali kv
- var kvUrl = config.KvUrl;
- _redisConfig = ConfigurationOptions.Parse(kvUrl);
- _redisConfig.Password = config.KvPassword;
- _redisConfig.SetDefaultPorts(); //自动填充默认端口
- var connection = ConnectionMultiplexer.Connect(_redisConfig);
- _db = connection.GetDatabase();
- _server = GetServer();
- }
- private IServer GetServer()
- {
- var config = new ConfigurationOptions
- {
- KeepAlive = 0,
- EndPoints = { _redisConfig.EndPoints[0]},
- AbortOnConnectFail = false,
- AllowAdmin = true
- };
- var conn = ConnectionMultiplexer.Connect(config);
- return conn.GetServer(config.EndPoints[0]);
- }
- public Task<RedisResult> EvalLua(string lua, IList<RedisKey> keys, IList<RedisValue> values)
- {
- if (_keyPrefix != null)
- keys = keys.Select(p => p.Prepend(_keyPrefix)).ToList();//加上前缀
- return _db.ScriptEvaluateAsync(lua, keys.ToArray(), values.ToArray());
- }
- public async Task<RedisResult> EvalLua(byte[] luaSha1, IList<RedisKey> keys, IList<RedisValue> values)
- {
- if (_keyPrefix != null)
- keys = keys.Select(p => p.Prepend(_keyPrefix)).ToList();//加上前缀
- return await _db.ScriptEvaluateAsync(luaSha1, keys.ToArray(), values.ToArray());
- }
- public async Task<byte[]> LoadLuaToServerAsync(string lua)
- {
- var sha1 = lua.CalcLuaSha1();//本地计算
- if(!await _server.ScriptExistsAsync(sha1))//服务器上不存在
- sha1 = await _server.ScriptLoadAsync(lua);//应该和计算的相同
- return sha1;
- }
- }
- }
下面是测试代码段
- //下面是测试代码
- [Test]
- public async Task LoadLuaToServerAsync()
- {
- var key = "TestEvalLua10010";
- var fieldContent = "testlua10011";
- const string lua =
- "redis.call('SET', KEYS[1], ARGV[1])\n" +
- "return redis.call('GET', KEYS[1])\n";
- var sha2 = lua.CalcLuaSha1();
- var sha1 = await _kv.LoadLuaToServerAsync(lua);
- Assert.AreEqual(20, sha1.Length);
- for (var i = 0; i < 20; i++)
- Assert.AreEqual(sha1[i],sha2[i]);
- var keys = new List<RedisKey> { key };
- var values = new List<RedisValue> { fieldContent };
- var result = await _kv.EvalLua(sha1, keys, values);
- Assert.AreEqual(fieldContent, (string)result);
- }
计算sha1用到的方法