一、概述

由于架构设计一里面如果多平台公用相同Key的缓存更改配置后需要多平台上传最新的缓存配置文件来更新,比较麻烦,更新了架构设计二实现了缓存配置的集中管理,不过这样有有了过于中心化的问题,后续在看看如何修改

总体设计思路如下:

项目结构如下:

二、服务端(提供Key配置文件管理及将Key配置存到缓存中)

KeyConfigList.xml缓存Key配置文件【与前一版一致】

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- name:程序key、key:缓存key(用:冒号来对缓存数据进行分级)、 validTime:有效时间(单位:分)、enabled:是否有效、{0}:占位符替换相关id等标识 -->
<list>
<!-- 一个占位符key -->
<item name="Admin_User_Session" key="Admin:User:Session:{0}" validTime="60" enabled="true"></item>
<!-- 无占位符key -->
<item name="Admin_User_List" key="Admin:User:List" validTime="30" enabled="true"></item>
<!-- 多个占位符key -->
<item name="Admin_User_Search" key="Admin:User:Search:{0}:{1}:{2}" validTime="5" enabled="true"></item> </list>
</configuration>

KeyConfigList.xml

KeyEntity.cs是对应xml文件的数据实体类(与客户端通用)

    /// <summary>
/// Key配置对象(公开)
/// Author:taiyonghai
/// CreateTime:2017-08-28
/// </summary>
public sealed class KeyEntity
{
private string name;
/// <summary>
/// Cache Name(Use for search cache key)
/// </summary>
public string Name
{
get { return name; }
set { name = value.Trim().ToLower(); }
} private string key;
/// <summary>
/// Cache Key
/// </summary>
public string Key
{
get { return key; }
set { key = value.Trim().ToLower(); }
} /// <summary>
/// Valid Time (Unit:minute)
/// </summary>
public int ValidTime { get; set; } /// <summary>
/// Enaled
/// </summary>
public bool Enabled { get; set; }
}

KeyEntity.cs

RedisManager.cs是Redis的管理类使用的StackExchange.Redis.dll(与客户端通用)

    /// <summary>
/// Redis缓存管理类
/// Author:taiyonghai
/// CreateTime:2017-08-28
/// </summary>
public static class RedisManager
{
//Redis连接对象
private static IConnectionMultiplexer redisMultiplexer;
//程序锁
private static object objLock = new object();
//Redis连接串(多个服务器用逗号隔开)"10.11.12.237:6379, password='',keepalive=300,connecttimeout=5000,synctimeout=1000"
private static readonly string connectStr = "10.11.12.237:6379"; /// <summary>
/// 静态构造用于注册监听事件
/// </summary>
static RedisManager()
{
//注册事件
GetMultiplexer().ConnectionFailed += ConnectionFailed;
GetMultiplexer().InternalError += InternalError;
GetMultiplexer().ErrorMessage += ErrorMessage;
}
/// <summary>
/// 连接失败
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
//e.Exception
}
/// <summary>
/// 内部错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void InternalError(object sender, InternalErrorEventArgs e)
{
//e.Exception
}
/// <summary>
/// 发生错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ErrorMessage(object sender, RedisErrorEventArgs e)
{
//e.Message
}
/// <summary>
/// 获得连接对象
/// </summary>
/// <returns></returns>
private static IConnectionMultiplexer GetMultiplexer()
{
if (redisMultiplexer == null || !redisMultiplexer.IsConnected)
{
lock (objLock)
{
//创建Redis连接对象
redisMultiplexer = ConnectionMultiplexer.Connect(connectStr);
}
}
return redisMultiplexer;
}
/// <summary>
/// 获得客户端对象
/// </summary>
/// <param name="db">选填指明使用那个数据库0-16</param>
/// <returns></returns>
public static IDatabase GetClient(int db = -)
{
return GetMultiplexer().GetDatabase(db);
} }

RedisManager.cs

KeyServer.cs是提供缓存配置文件管理、监听、存储等功能的核心类

    /// <summary>
/// 缓存Key管理
/// Author:taiyonghai
/// CreateTime:2017-08-28
/// </summary>
public static class KeyServer
{
//缓存MQ监听的Key[需要与客户端相同]
private static string mqConfigKey = "MQConfigKey";
//缓存Key配置的Key[需要与客户端相同]
private static string cacheConfigKey = "CacheConfigKey";
//KeyName集合
private static List<HashEntry> keyConfigList;
//锁对象
private static object objLock = new object();
//监控文件对象
private static FileSystemWatcher watcher;
//缓存Key配置文件路径
private static readonly string configFilePath = AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin\\Debug", String.Empty) + "Server\\Configs\\";
//缓存Key配置文件名
private static readonly string configFileName = "KeyConfigList.xml"; /// <summary>
/// 静态构造只执行一次
/// </summary>
static KeyServer()
{
try
{
//创建对配置文件夹的监听,如果遇到文件更改则清空KeyNameList,重新读取
watcher = new FileSystemWatcher();
watcher.Path = configFilePath;//监听路径
watcher.Filter = configFileName;//监听文件名
watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.Size;//仅监听文件创建时间、文件变更时间、文件大小
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;//最后开启监听
}
catch (Exception e)
{
throw new ApplicationException("创建监听程序错误,检查监听路径或文件是否存在");
}
//初始执行一次读取文件并存入缓存
ReaderKeyFile();
} /// <summary>
/// 读取KeyName文件
/// </summary>
private static void ReaderKeyFile()
{
if (keyConfigList == null || keyConfigList.Count == )
{
//锁定读取xml操作
lock (objLock)
{
//获取配置文件
string configFile = String.Concat(configFilePath, configFileName);
//检查文件
if (!File.Exists(configFile))
{
throw new FileNotFoundException(String.Concat("file not exists:", configFile));
} //读取xml文件
XmlReaderSettings xmlSetting = new XmlReaderSettings();
xmlSetting.IgnoreComments = true;//忽略注释
XmlReader xmlReader = XmlReader.Create(configFile, xmlSetting);
//一次读完整个文档
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
xmlReader.Close();//关闭读取对象 //获取指定节点下的所有子节点
XmlNodeList nodeList = xmlDoc.SelectSingleNode("//configuration//list").ChildNodes; //获得一个线程安全的Hashtable对象
keyConfigList = new List<HashEntry>(); //将xml中的属性赋值给Hashtable
foreach (XmlNode node in nodeList)
{
XmlElement element = (XmlElement)node;//转为元素获取属性 KeyEntity entity = new KeyEntity();
entity.Name = element.GetAttribute("name");
entity.Key = element.GetAttribute("key");
entity.ValidTime = Convert.ToInt32(element.GetAttribute("validTime"));
entity.Enabled = Convert.ToBoolean(element.GetAttribute("enabled")); keyConfigList.Add(new HashEntry(entity.Name, JsonSerializer.SerializeToString(entity)));
}
//存入缓存
RedisManager.GetClient().HashSet(cacheConfigKey, keyConfigList.ToArray());
}
}
} /// <summary>
/// 变更事件会触发两次是正常情况,是系统保存文件机制导致
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private static void OnChanged(object source, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Changed)
{
if (e.Name.ToLower() == configFileName.ToLower())
{
keyConfigList = null;
RedisManager.GetClient().KeyDelete(cacheConfigKey);
ReaderKeyFile();
//因为此事件会被调用两次,所以里面的代码要有幕等性
}
}
} /// <summary>
/// 重建缓存配置
/// </summary>
private static void RebuildCacheConfig()
{
//本地静态对象有值则直接存入Cache,无值则重新读取物理文件
if (keyConfigList == null || keyConfigList.Count == )
ReaderKeyFile();
else
RedisManager.GetClient().HashSet(cacheConfigKey, keyConfigList.ToArray());
} /// <summary>
/// 监视缓存配置消息
/// </summary>
public static void MonitorCacheConfigMsg()
{
//读取队列是否有消息(采用有序集合的方式代替队列避免并发请求时重复消息过多去重的操作)
//var value = RedisManager.GetClient().ListLeftPop(mqConfigKey);
var value = RedisManager.GetClient().SortedSetRangeByRank(mqConfigKey);
if (value.Length > )
{
//检查缓存是否存在配置信息
var hash = RedisManager.GetClient().HashGetAll(cacheConfigKey);
if (hash == null || hash.Length == )
{
//不存在则重建配置
RebuildCacheConfig();
}
//重建后删除有序集合中的消息
RedisManager.GetClient().SortedSetRemove(mqConfigKey, );
}
}
}

KeyServer.cs

服务端会读取消息来监控缓存是否含有配置信息所以服务端需要挂在成一个WindowsService服务

    class Program
{
static void Main(string[] args)
{
while (true)
{
try
{
KeyServer.MonitorCacheConfigMsg();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
System.Threading.Thread.Sleep();
}
}
}

测试调用代码

三、客户端(根据KeyNames获取缓存中的配置,然后根据配置读取缓存数据或创建缓存数据,如果没有配置则会返回NULL并发送消息申请创建缓存配置,主业务不会中断会直接穿透到数据库取值)

KeyEntity.cs 和 RedisManager.cs的代码和服务端的一致,有需要拷贝即可!

CacheProvider.cs是对外提供缓存功能的类【与前一版一致】

    /// <summary>
/// 缓存提供类
/// Author:taiyonghai
/// CreateTime:2017-08-28
/// </summary>
public class CacheProvider
{ #region Cache 删除 /// <summary>
/// 删除缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>True成功,Flase失败</returns>
public static bool DelKey(KeyNames name)
{
return DelKey(name, null);
}
/// <summary>
/// 删除缓存[核心]
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>True成功,Flase失败</returns>
public static bool DelKey(KeyNames name, params string[] identities)
{
var entity = KeyClient.Get(name, identities);
if (null == entity)
return false;
else
return RedisManager.GetClient().KeyDelete(entity.Key);
} #endregion #region Cache String 存取 #region 添加缓存 /// <summary>
/// 添加缓存,有过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="value">不可为NULL,应对缓存穿透请用空</param>
/// <returns>True成功,Flase失败</returns>
public static bool SetString<T>(KeyNames name, T value) where T : class, new()
{
return SetString<T>(name, value, null);
}
/// <summary>
/// 添加缓存,有过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="value">不可为NULL,应对缓存穿透请用空</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>True成功,Flase失败</returns>
public static bool SetString<T>(KeyNames name, T value, params string[] identities) where T : class, new()
{
//如果value为null直接缓存无需序列化
string tmpStr = null == value ? null : JsonConvert.SerializeObject(value);
return SetString(name, tmpStr, identities);
}
/// <summary>
/// 添加缓存,有过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="value">不可为NULL,应对缓存穿透请用空</param>
/// <returns>True成功,Flase失败</returns>
public static bool SetString(KeyNames name, string value)
{
return SetString(name, value, null);
}
/// <summary>
/// 添加缓存,有过期时间[核心](如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="value">不可为NULL,应对缓存穿透请用空</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>True成功,Flase失败</returns>
public static bool SetString(KeyNames name, string value, params string[] identities)
{
//不可传值为NULL,应对缓存穿透请用空,NULL用来判断是否缓存有值
if (null == value)
return false;
var entity = KeyClient.Get(name, identities);
if (null == entity)
return false;
else
{
//有效时间的TimeSpan=(最小时间+有效时间)-最小时间
TimeSpan timeSpan = DateTime.MinValue.AddMinutes(entity.ValidTime) - DateTime.MinValue;
return RedisManager.GetClient().StringSet(entity.Key, value, timeSpan);
}
} #endregion #region 获取缓存 /// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static T GetString<T>(KeyNames name) where T : class, new()
{
return GetString<T>(name, null);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static T GetString<T>(KeyNames name, params string[] identities) where T : class, new()
{
string tmpStr = GetString(name, identities);
//如果tmpStr为null直接返回无需反序列化
return null == tmpStr ? default(T) : JsonConvert.DeserializeObject<T>(tmpStr);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static string GetString(KeyNames name)
{
return GetString(name, null);
}
/// <summary>
/// 获取缓存[核心]
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static string GetString(KeyNames name, params string[] identities)
{
var entity = KeyClient.Get(name, identities);
if (null == entity)
return null;
else
{
//检查缓存是否启用,否则返回NULL
if (entity.Enabled)
{
return RedisManager.GetClient().StringGet(entity.Key);
}
else
{
//如果停用缓存,则删除
DelKey(name);
return null;
}
}
} #endregion #endregion #region Cache Hash 存取 #region 添加缓存 /// <summary>
/// 添加缓存,无过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="dict">不可为NULL,应对缓存穿透请用空对象</param>
public static bool SetHash<T>(KeyNames name, Dictionary<string, T> dict) where T : class, new()
{
return SetHash<T>(name, dict, null);
}
/// <summary>
/// 添加缓存,无过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="dict">不可为NULL,应对缓存穿透请用空对象</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
public static bool SetHash<T>(KeyNames name, Dictionary<string, T> dict, params string[] identities) where T : class, new()
{
var tmpDict = new Dictionary<string, string>();
foreach (var item in dict)
tmpDict.Add(item.Key, null == item.Value ? null : JsonConvert.SerializeObject(item.Value));
return SetHash(name, tmpDict, identities);
}
/// <summary>
/// 添加缓存,无过期时间(如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="dict">不可为NULL,应对缓存穿透请用空对象</param>
public static bool SetHash(KeyNames name, Dictionary<string, string> dict)
{
return SetHash(name, dict, null);
}
/// <summary>
/// 添加缓存,无过期时间[核心](如Key存在则更新值)
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="dict">不可为NULL,应对缓存穿透请用空对象</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
public static bool SetHash(KeyNames name, Dictionary<string, string> dict, params string[] identities)
{
//不可传值为NULL,应对缓存穿透请用空对象,NULL用来判断是否缓存有值
if (null == dict)
return false;
var entity = KeyClient.Get(name, identities);
if (null == entity)
return false;
else
{
var hashEntryList = new List<HashEntry>();
foreach (var item in dict)
hashEntryList.Add(new HashEntry(item.Key, item.Value));
RedisManager.GetClient().HashSet(entity.Key, hashEntryList.ToArray());
return true;
}
} #endregion #region 获取缓存 /// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static Dictionary<string, T> GetHash<T>(KeyNames name) where T : class, new()
{
return GetHash<T>(name, null);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static Dictionary<string, T> GetHash<T>(KeyNames name, params string[] identities) where T : class, new()
{
var dict = GetHash(name, identities);
if (null == dict)
return null;
else
{
var tmpDict = new Dictionary<string, T>();
foreach (var item in dict)
tmpDict.Add(item.Key, null == item.Value ? default(T) : JsonConvert.DeserializeObject<T>(item.Value));
return tmpDict;
}
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static Dictionary<string, string> GetHash(KeyNames name)
{
return GetHash(name, null);
}
/// <summary>
/// 获取缓存[核心]
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>无缓存或禁用缓存均返回NULL</returns>
public static Dictionary<string, string> GetHash(KeyNames name, params string[] identities)
{
var entity = KeyClient.Get(name, identities);
if (null == entity)
return null;
else
{
//检查缓存是否启用,否则返回NULL
if (entity.Enabled)
{
var hashEntry = RedisManager.GetClient().HashGetAll(entity.Key);
var dict = new Dictionary<string, string>();
foreach (var item in hashEntry)
dict.Add(item.Name, item.Value);
return dict;
}
else
{
//如果停用缓存,则删除
DelKey(name);
return null;
}
}
} #endregion #endregion

CacheProvider.cs

MQProvider.cs是对外提供队列功能的类【与前一版一致】

    /// <summary>
/// 队列提供类
/// Author:taiyonghai
/// CreateTime:2017-08-31
/// </summary>
public class MQProvider
{
#region MQ 添加 /// <summary>
/// 添加一条消息到队列
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="msg">内容</param>
/// <returns></returns>
public long SetMsg<T>(KeyNames name, T msg)
{
return SetMsg<T>(name, msg, null);
}
/// <summary>
/// 添加一条消息到队列
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="msg">内容</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns></returns>
public long SetMsg<T>(KeyNames name, T msg, params string[] identities)
{
//如果value为null直接缓存无需序列化
string tmpMsg = null == msg ? null : JsonSerializer.SerializeToString<T>(msg);
return SetMsg(name, tmpMsg, identities);
}
/// <summary>
/// 添加一条消息到队列
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="msg">内容</param>
/// <returns></returns>
public long SetMsg(KeyNames name, string msg)
{
return SetMsg(name, msg, null);
}
/// <summary>
/// 添加一条消息到队列[核心]
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="msg">内容</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>添加消息后的队列长度</returns>
public long SetMsg(KeyNames name, string msg, params string[] identities)
{
var entity = KeyClient.Get(name, identities);
//向队列右侧插入新的消息
return RedisManager.GetClient().ListRightPush(entity.Key, msg);
} #endregion #region MQ 获取 /// <summary>
/// 从队列中获取一条消息,并将其在队列中移除
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>没有消息返回NULL</returns>
public T GetMsg<T>(KeyNames name)
{
return GetMsg<T>(name, null);
}
/// <summary>
/// 从队列中获取一条消息,并将其在队列中移除
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>没有消息返回NULL</returns>
public T GetMsg<T>(KeyNames name, params string[] identities)
{
string tmpStr = GetMsg(name, identities);
return null == tmpStr ? default(T) : JsonSerializer.DeserializeFromString<T>(tmpStr);
}
/// <summary>
/// 从队列中获取一条消息,并将其在队列中移除
/// </summary>
/// <param name="name">Key名称</param>
/// <returns>没有消息返回NULL</returns>
public string GetMsg(KeyNames name)
{
return GetMsg(name, null);
}
/// <summary>
/// 从队列中获取一条消息,并将其在队列中移除[核心]
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns>没有消息返回NULL</returns>
public string GetMsg(KeyNames name, params string[] identities)
{
var entity = KeyClient.Get(name, identities);
//从队列左侧队列头部取出消息
return RedisManager.GetClient().ListLeftPop(entity.Key);
} #endregion
}

MQProvider.cs

KeyNames.cs配置缓存Key的名称,用于寻找Key配置【与前一版一致】

    /// <summary>
/// KeyName枚举(公开)
/// Author:taiyonghai
/// CreateTime:2017-08-28
/// </summary>
public enum KeyNames
{
/// <summary>
/// 后台用户会话key
/// </summary>
Admin_User_Session, Admin_User_List, Admin_User_Search }

KeyNames.cs

KeyClient.cs是对于使用缓存时寻找Key对应配置信息的核心类

    public class KeyClient
{
//缓存MQ监听的Key[需要与服务端相同]
private static string mqConfigKey = "MQConfigKey";
//缓存Key配置的Key[需要与服务端相同]
private static string cacheConfigKey = "CacheConfigKey"; /// <summary>
/// 根据KeyName获取Key配置对象
/// </summary>
/// <param name="name">Key名称</param>
/// <returns></returns>
public static KeyEntity Get(KeyNames name)
{
return Get(name, null);
}
/// <summary>
/// 根据KeyName获取Key配置对象
/// </summary>
/// <param name="name">Key名称</param>
/// <param name="identities">Key标识(用于替换Key中的{0}占位符)</param>
/// <returns></returns>
public static KeyEntity Get(KeyNames name, params string[] identities)
{
var value = RedisManager.GetClient().HashGet(cacheConfigKey, name.ToString().ToLower());
if (value.HasValue)
{
var entity = JsonSerializer.DeserializeFromString<KeyEntity>(value);
//检查Key是否需要含有占位符
if (entity.Key.IndexOf('{') > )
{
//检查参数数组是否有值
if (identities != null && identities.Length > )
entity.Key = String.Format(entity.Key, identities);
else
throw new ArgumentException("需要此参数identities标识字段,但并未传递", "identities");
}
return entity;
}
else
{
//异步发送消息
SendCreateConfigMsg();
return null;
}
}
public static async Task<bool> SendCreateConfigMsg()
{
//发送消息重建缓存配置(采用有序集合的方式代替队列避免并发请求时重复消息过多去重的操作)
//RedisManager.GetClient().ListRightPush(mqConfigKey, 0);
return await RedisManager.GetClient().SortedSetAddAsync(mqConfigKey, , DateTime.Now.Ticks);
}
}

KeyClient.cs

客户端使用只会接触到CacheProvider.cs和MQProvider.cs两个对外开放的操作类

使用步骤:

1、向KeyNames.cs中添加一个唯一的KeyName用于找到指定的Key配置;

2、向服务端的KeyConfigList.xml中添加此KeyName的缓存配置(此功能的提供方式可以自己定义,如直接修改文件或提供管理程序等);

3、使用Cache或者MQ的操作类传递KeyNames的枚举值,再传递缓存值即可;

    public class HomeController : Controller
{
public ActionResult Index()
{
CacheProvider.SetString(KeyNames.Admin_User_List, "test");
string str = CacheProvider.GetString(KeyNames.Admin_User_List);
return View();
}
}

测试调用代码

如有什么可以改进的地方还请不吝指点,谢谢

Redis缓存项目应用架构设计二的更多相关文章

  1. Redis缓存项目应用架构设计一

    一些项目整理出的项目中引入缓存的架构设计方案,希望能帮助你更好地管理项目缓存,作者水平有限,如有不足还望指点. 一.基础结构介绍 项目中对外提供方法的是CacheProvider和MQProvider ...

  2. 《【面试突击】— Redis篇》--Redis Cluster及缓存使用和架构设计的常见问题

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>--Redis Cluster及缓存使用和架构设计的 ...

  3. APP和服务端-架构设计(二)

    1. App架构设计经验谈:接口的设计 App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 1.1 安全机制的设计 现在,大部分App的接口 ...

  4. python-django电商项目-需求分析架构设计数据库设计_20191115

    python-django电商项目需求分析 1.用户模块 1)注册页 注册时校验用户名是否已被注册. 完成用户信息的注册. 给用户的注册邮箱发送邮件,用户点击邮件中的激活链接完成用户账户的激活. 2) ...

  5. WCF项目的架构设计

    本文将介绍以WCF开发项目为主的架构设计,主要从类库的分类和代码的结构. 下面将以一个WCF实例做具体的介绍.此项目底层是一个Windows Service,WCF服务Hosted在此Windows ...

  6. 高可用Redis(十三):Redis缓存的使用和设计

    1.缓存的受益和成本 1.1 受益 1.可以加速读写:Redis是基于内存的数据源,通过缓存加速数据读取速度 2.降低后端负载:后端服务器通过前端缓存降低负载,业务端使用Redis降低后端数据源的负载 ...

  7. GPS部标平台的架构设计(二) 可扩展性设计

    在设计的前夕,设计人员喜欢把领导对未来业务的期望带入到设计目标当中,比如当前业务也不过是接入几千辆车,未来业务增长也不过几万台,但领导很多激情,强势要求二期平台的接入能力要达到20万台,这个要求带入到 ...

  8. Redis缓存数据库安全加固指导(二)

    背景 在众多开源缓存技术中,Redis无疑是目前功能最为强大,应用最多的缓存技术之一,参考2018年国外数据库技术权威网站DB-Engines关于key-value数据库流行度排名,Redis暂列第一 ...

  9. saltstack主机管理项目:主机管理项目架构设计(二)

    1.salt架构图 https://docs.saltstack.com/en/getstarted/system/plugins.html plug-ins(左边):场景可插拔 subsystem- ...

随机推荐

  1. 九九乘法表实现---基于python

    # coding:utf-8"""九九乘法表"""for k in range(1,10):    for i in range(1,k+1 ...

  2. RMI和socket详解

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp58   一般来说,基于CS(client-server)软件架构的开发技 ...

  3. ORACLE ROWNUM解析

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp53 [align=middle;" align="le ...

  4. zookeeper原理介绍

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt354 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它 ...

  5. Linux-grep 命令和find 命令 (6)

    grep与find区别: grep:查找指定目录下过滤文本文件中行数据 find:查找指定目录下文件 grep使用 格式:   grep "text"   *  [选项] 选项: ...

  6. PHP初入,for循环使用

    一: 找出100-999之间的所有"水仙花数".所谓水仙花数是指一个三位 数,各位数字的立方和等于该数本身.(如153次方=1的3次方+5的3次方+3的3次方)并输出这些数字 想想 ...

  7. 201521123075 《Java程序设计》第2周学习总结

    1. 本周学习总结 各种数据类型,运算符,表达式的使用: 字符串String类; 对数组对象和字符串对象的运用. 2. 书面作业 1.使用Eclipse关联jdk源代码,并查看String对象的源代码 ...

  8. 201521123090《JAVA程序设计》第二周学习总结

    1. 本章学习总结 java基本数据类型 String类对象使用 枚举类型及switch分支 容器的概念 2. 书面作业 Q1.使用Eclipse关联jdk源代码(截图),并查看String对象的源代 ...

  9. 201521123003《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  10. 201521123022 《Java程序设计》 第十二周学习总结

    1. 本周学习总结 2. 书面作业 Q1.将Student对象(属性:int id, String name,int age,double grade)写入文件student.data.从文件读出显示 ...