Redis(3)-使用StackExchange.Redis進行CRUD

ServiceStack.Redis原來從v4就開始收費(但v3沒這問題),

目的為支援小專案和評估,所以我又回頭使用StackExchange.Redis進行CRUD。

前天正當我想把SQL Server一些資料表轉入Redis時,

使用ServiceStack.Redis居然出現每小時不能超過6000的request錯誤,

查看官方網頁得知,原來從v4開始免費版本有些限制(如下圖)

圖片來源: servicestack.net

 

但ServiceStack.Redis處理entity真的很方便又高效能,於是我追了一下Sourcecode並重新recompile為XX終極測試版

(我擷取部分sourcecode,如果覺得好用還請付費支持)

話雖如此,公司還是要使用正式版本,於是我又轉回使用StackExchange.Redis(使用上還須注意不少Redis.config設定)。

直接看code

Program _Program = new Program();
            //_Program.Flushdb();

            //insert
            _Program.Insert();
            //Select
            RedisKey[] mykeys = { "User1", "User2", "User3" };//注意大小寫
            _Program.GetUser(mykeys);
            //update
            _Program.Update("User1", "ricoisme", DateTime.Parse( "1981-12-13"));
            _Program.GetUser(mykeys);

            //delete
            _Program.DeleteUser("User1");
            _Program.GetUser(mykeys);

private void Insert()
        {
            StackExchangeRedisHelper _StackExchangeRedisHelper = new StackExchangeRedisHelper();
            conn = _StackExchangeRedisHelper.SafeConn;//create safe connection

            if (conn == null || !conn.IsConnected)
            {
                Console.WriteLine("No connection is available");
                return;
            }
            IDatabase database = conn.GetDatabase();

            var user1 = new User
            {
                ID = 1,
                Name = "rico",
                Birthday = DateTime.Parse("1982-01-01 12:12:12"),
                Sex = true
            };

            var user2 = new User
            {
                ID = 2,
                Name = "sherry",
                Birthday = DateTime.Parse("1982-02-01 12:12:12"),
                Sex = false
            };

            var user3 = new User
            {
                ID = 3,
                Name = "fifi",
                Birthday = DateTime.Parse("1982-03-01 12:12:12"),
                Sex = false
            };

            //key要注意大小寫
            if (_StackExchangeRedisHelper.Add<User>(database, "User" + user1.ID, user1))
            {
                Console.WriteLine("User" + user1.ID + " has inserted");
            }
            else
            {
                Console.WriteLine("User" + user1.ID + " insert failed");
            }
            if (_StackExchangeRedisHelper.Add<User>(database, "User" + user2.ID, user2))
            {
                Console.WriteLine("User" + user2.ID + " has inserted");
            }
            else
            {
                Console.WriteLine("User" + user2.ID + " insert failed");
            }
            if (_StackExchangeRedisHelper.Add<User>(database, "User" + user3.ID, user3))
            {
                Console.WriteLine("User" + user3.ID + " has inserted");
            }
            else
            {
                Console.WriteLine("User" + user3.ID + " insert failed");
            }
        }

        public void GetUser(RedisKey[] keys)
        {
            StackExchangeRedisHelper _StackExchangeRedisHelper = new StackExchangeRedisHelper();
            conn = _StackExchangeRedisHelper.SafeConn;//create safe connection
            IDatabase database = conn.GetDatabase();

            var datas = _StackExchangeRedisHelper.Get<User>(database, keys);
            if (datas == null)
                Console.WriteLine("No Data");
            else
            {
                foreach (var data in datas)
                {
                    Console.WriteLine("ID:{0} ,Name:{1}, Birthday:{2}, Sex:{3}",
                   data.ID, data.Name, data.Birthday.ToShortDateString(), data.Sex);
                }
            }
        }

        public void DeleteUser(string key)
        {
            StackExchangeRedisHelper _StackExchangeRedisHelper = new StackExchangeRedisHelper();
            conn = _StackExchangeRedisHelper.SafeConn;//create safe connection
            IDatabase database = conn.GetDatabase();
            if (_StackExchangeRedisHelper.DeleteKey(database, key))
                Console.WriteLine("Delete OK");
            else
                Console.WriteLine("Delete failed");
        }

        public void Update(string key, string name, DateTime birthday)
        {
            StackExchangeRedisHelper _StackExchangeRedisHelper = new StackExchangeRedisHelper();
            conn = _StackExchangeRedisHelper.SafeConn;//create safe connection
            IDatabase database = conn.GetDatabase();

            var data = _StackExchangeRedisHelper.Get<User>(database, key);
            if (data == null)
                Console.WriteLine("No Data");
            else
            {
                data.Name = name;
                data.Birthday = birthday;
                _StackExchangeRedisHelper.Add<User>(database, key, data);
            }
        }
public class StackExchangeRedisHelper
    {
        private Lazy<ConnectionMultiplexer> conn = null;
        private IServer redisserver = null;
        public StackExchangeRedisHelper()
        {
            try
            {
                conn = new Lazy<ConnectionMultiplexer>(
      () => ConnectionMultiplexer.Connect(configOptions.Value));
            }
            catch
            {
                throw;
            }
        }

        public ConnectionMultiplexer SafeConn
        {
            get
            {
                return conn.Value;
            }
        }

        public IServer RedisServer
        {
            get
            {
                string _RedisServer = ConfigurationManager.AppSettings["RedisServer"];
                int _RedisPort = int.Parse(ConfigurationManager.AppSettings["RedisPort"]);

                redisserver = conn.Value.GetServer(_RedisServer, _RedisPort);
                return redisserver;
            }
        }

        
        private Lazy<ConfigurationOptions> configOptions
            = new Lazy<ConfigurationOptions>(() =>
            {
                var configOptions = new ConfigurationOptions();
                string RedisServer = ConfigurationManager.AppSettings["RedisServer"];
                int RedisPort = int.Parse(ConfigurationManager.AppSettings["RedisPort"]);
                string ClientName = ConfigurationManager.AppSettings["ClientName"];
                bool allowAdmin = bool.Parse(ConfigurationManager.AppSettings["allowAdmin"]);
                bool ssl = bool.Parse(ConfigurationManager.AppSettings["ssl"]);
                int ConnectTimeout = int.Parse(ConfigurationManager.AppSettings["connectTimeout"]);//5 sec               
                configOptions.EndPoints.Add(RedisServer, RedisPort);
                configOptions.ClientName = ClientName;
                configOptions.ConnectTimeout = ConnectTimeout;
                configOptions.SyncTimeout = int.MaxValue;
                configOptions.AllowAdmin = allowAdmin;//need Flushdb
                configOptions.Ssl = ssl;
                /*
                 StackExchange.Redis won't reconnect to the server automatically under some conditions. 
                 We strongly recommend that you set abortConnect=false in your connection string so that SE.
                 Redis will auto-reconnect in the background if a network blip occurs.
                 */
                configOptions.AbortOnConnectFail = false;
                return configOptions;
            });

        public bool Add<T>(IDatabase database, string key, T value, DateTimeOffset? expiresAt = null) where T : class
        {
            //serialize
            var serializedObject = JsonConvert.SerializeObject(value);
            if (expiresAt.HasValue)
            {
                var expiration = expiresAt.Value.Subtract(DateTimeOffset.Now);
                return database.StringSet(key, serializedObject, expiration);
            }
            return database.StringSet(key, serializedObject);
        }

        public bool DeleteKey(IDatabase database, string key)
        {
            return database.KeyDelete(key);
        }

        public T Get<T>(IDatabase database, string key) where T : class
        {
            var serializedObject = database.StringGet(key);
            //deserialize
            return JsonConvert.DeserializeObject<T>(serializedObject);
        }

        public IEnumerable<T> Get<T>(IDatabase database, RedisKey[] keys) where T : class
        {
            var AllserializedObject = database.StringGet(keys);
            //deserialize
            List<T> allvalues = new List<T>();
            foreach (RedisValue data in AllserializedObject)
            {
                if (data.HasValue)
                    allvalues.Add(JsonConvert.DeserializeObject<T>(data));
            }
            return allvalues;
        }

    }

 

 

Note:也可以透過StackExchange.Redis.Extensions實作。

 

 

 

參考

booksleeve

So I went and wrote another Redis client…

StackExchange.Redis

StackExchange.Redis.Extensions