using Newtonsoft.Json; using StackExchange.Redis; namespace Server.System { public class Redis { ConnectionMultiplexer redis; IDatabase db; bool local = false; Dictionary stringType; Dictionary> listType; Dictionary> zType; Dictionary> hashType; //일반적인 사용에는 문제가 없지만 값을 비교해야 할때는 다음과 같이 변환이필요 //if(redis에서 가져온값 == (object)(StackExchange.Redis.RedisValue)비교하고 싶은 값) public Redis(string host = "127.0.0.1", int port = 6379, int db = 0, string password = "") { if (host == "localhost") { local = true; stringType = new Dictionary(); listType = new Dictionary>(); zType = new Dictionary>(); hashType = new Dictionary>(); } else { if (password.Equals(string.Empty)) { redis = ConnectionMultiplexer.Connect($"{host}:{port}"); this.db = redis.GetDatabase(db); } else { ConfigurationOptions options = new ConfigurationOptions { EndPoints = { $"{host}:{port}" }, Password = password }; redis = ConnectionMultiplexer.Connect(options); this.db = redis.GetDatabase(db); } } } public void SetString(string value, params string[] keys) { if (local) { if (stringType.ContainsKey(KeySet(keys))) stringType[KeySet(keys)] = value; else stringType.Add(KeySet(keys), value); } else db.StringSet(KeySet(keys), JsonConvert.SerializeObject(value)); } public string GetString(params string[] keys) { if (local) return stringType[KeySet(keys)]; else return db.StringGet(key: KeySet(keys)); } public void SetList(T value, params string[] keys) { if (local) { if (listType.ContainsKey(KeySet(keys))) listType[KeySet(keys)].Add(JsonConvert.SerializeObject(value)); else listType.Add(KeySet(keys), [JsonConvert.SerializeObject(value)]); } else db.ListRightPush(KeySet(keys), JsonConvert.SerializeObject(value)); } public void UpdateList(int index, T value, params string[] keys) { if (local) listType[KeySet(keys)][index] = JsonConvert.SerializeObject(value); else db.ListSetByIndex(KeySet(keys), index, JsonConvert.SerializeObject(value)); } public void RemoveList(int index, T value, params string[] keys) { if (local) listType[KeySet(keys)].RemoveAt(index); else db.ListRemove(KeySet(keys), JsonConvert.SerializeObject(value), index); } public void SetList(List value, params string[] keys) { foreach (var item in value) { SetList(item, keys); } } public T GetList(long index, params string[] keys) { if (local) return JsonConvert.DeserializeObject(listType[KeySet(keys)][(int)index]); else return JsonConvert.DeserializeObject(db.ListGetByIndex(KeySet(keys), index)); } public List GetList(params string[] keys) { List result = new List(); if (local) { List strings = listType[KeySet(keys)]; foreach (var item in strings) { result.Add(JsonConvert.DeserializeObject(item)); } } else { RedisValue[] strings = db.ListRange(KeySet(keys)); foreach (var item in strings) { result.Add(JsonConvert.DeserializeObject(item)); } } return result; } public void SetZ(string value, double score, params string[] keys) { SetZ(new Rank(value, score), keys); } public void SetZ(Rank rank, params string[] keys) { if (local) { if (zType.ContainsKey(KeySet(keys))) zType[KeySet(keys)].Add(rank); else zType.Add(KeySet(keys), [rank]); zType[KeySet(keys)].OrderBy(r => r.score).ToList(); } else { db.SortedSetAdd(KeySet(keys), rank.value, rank.score); } } public double GetZScore(string value, params string[] keys) { if (local) return zType[KeySet(keys)].Find(n => n.value == value).score; else return (double)db.SortedSetScore(KeySet(keys), value); } public long GetZRank(string value, params string[] keys) { if (local) return zType[KeySet(keys)].FindIndex(n => n.value == value) + 1; else return (long)db.SortedSetRank(KeySet(keys), value); } public List GetZ(long rank, params string[] keys) { List result = new List(); if (local) { List ranking = new List(zType[KeySet(keys)]); if (ranking.Count > rank) for (long n = 0; n < rank; n++) result.Add(ranking[(int)n]); else result = new List(ranking); } else { var topRankEntries = db.SortedSetRangeByRank(KeySet(keys), 0, rank - 1); foreach (var entry in topRankEntries) result.Add(new Rank(entry, GetZScore(entry, keys))); } return result; } public void SetHash(string field, object value, params object[] keys) { if (local) { if (hashType.ContainsKey(KeySet(keys))) { Dictionary userHash = hashType[KeySet(keys)]; if (userHash.ContainsKey(field)) userHash[field] = value; else userHash.Add(field, value); } else hashType.Add(KeySet(keys), new Dictionary { { field, value } }); } else { db.HashSet(KeySet(keys), field, JsonConvert.SerializeObject(value)); } } public void SetHash(Dictionary hash, params object[] keys) { foreach (var item in hash) SetHash(item.Key, item.Value, keys); } public Dictionary GetAllHash(params string[] keys) { Dictionary hash = new Dictionary(); if (local) { Dictionary hashs; if (hashType.ContainsKey(KeySet(keys))) { hashs = hashType[KeySet(keys)]; foreach (var entry in hashs) hash.Add(entry.Key, entry.Value); } else { hashs = new Dictionary(); foreach (var entry in hashs) hash.Add(entry.Key, entry.Value); hashType.Add(KeySet(keys), hashs); } } else { HashEntry[] hashEntries = db.HashGetAll(KeySet(keys)); foreach (var entry in hashEntries) hash.Add(entry.Name, entry.Value); } return hash; } public object GetHash(string field ,params string[] keys) { if (local) { Dictionary hashs = new Dictionary(hashType[KeySet(keys)]); return hashs[field]; } else return db.HashGet(KeySet(keys), field); } public void RemoveHash(string field, params string[] keys) { if (local) hashType[KeySet(keys)].Remove(field); else db.HashDelete(KeySet(keys), field); } public void RemoveKey(params string[] keys) { if (local) { stringType.Remove(KeySet(keys)); listType.Remove(KeySet(keys)); zType.Remove(KeySet(keys)); hashType.Remove(KeySet(keys)); } else db.KeyDelete(KeySet(keys)); } private string KeySet(object[] keys) { return string.Join(":", keys); } public class Rank { public string value; public double score; public Rank(string value, double score) { this.value = value; this.score = score; } } } }