C# redis使用之ServiceStack
需要注意的是:ServiceStack.Redis 中GetClient()方法,只能拿到Master redis中获取连接,而拿不到slave 的readonly连接。这样 slave起到了冗余备份的作用,读的功能没有发挥出来,如果并发请求太多的话,则Redis的性能会有影响。
所以,我们需要的写入和读取的时候做一个区分,写入的时候,调用client.GetClient() 来获取writeHosts的Master的redis 链接。读取,则调用client.GetReadOnlyClient()来获取的readonlyHost的 Slave的redis链接。
或者可以直接使用client.GetCacheClient() 来获取一个连接,他会在写的时候调用GetClient获取连接,读的时候调用GetReadOnlyClient获取连接,这样可以做到读写分离,从而利用redis的主从复制功能。
1. 配置文件 app.config
<!-- redis Start -->
<add key="SessionExpireMinutes" value="180" />
<add key="redis_server_master_session" value="127.0.0.1:6379" />
<add key="redis_server_slave_session" value="127.0.0.1:6380" />
<add key="redis_max_read_pool" value="300" />
<add key="redis_max_write_pool" value="100" />
<!--redis end-->
2. Redis操作的公用类RedisCacheHelper
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web;
using ServiceStack.Common.Extensions;
using ServiceStack.Redis;
using ServiceStack.Logging;
namespace Weiz.Redis.Common
{
public class RedisCacheHelper
{
private static readonly PooledRedisClientManager pool = null;
private static readonly string[] writeHosts = null;
private static readonly string[] readHosts = null;
public static int RedisMaxReadPool = int.Parse(ConfigurationManager.AppSettings["redis_max_read_pool"]);
public static int RedisMaxWritePool = int.Parse(ConfigurationManager.AppSettings["redis_max_write_pool"]);
static RedisCacheHelper()
{
var redisMasterHost = ConfigurationManager.AppSettings["redis_server_master_session"];
var redisSlaveHost = ConfigurationManager.AppSettings["redis_server_slave_session"];
if (!string.IsNullOrEmpty(redisMasterHost))
{
writeHosts = redisMasterHost.Split(',');
readHosts = redisSlaveHost.Split(',');
if (readHosts.Length > 0)
{
pool = new PooledRedisClientManager(writeHosts, readHosts,
new RedisClientManagerConfig()
{
MaxWritePoolSize = RedisMaxWritePool,
MaxReadPoolSize = RedisMaxReadPool,
AutoStart = true
});
}
}
}
public static void Add<T>(string key, T value, DateTime expiry)
{
if (value == null)
{
return;
}
if (expiry <= DateTime.Now)
{
Remove(key);
return;
}
try
{
if (pool != null)
{
using (var r = pool.GetClient())
{
if (r != null)
{
r.SendTimeout = 1000;
r.Set(key, value, expiry - DateTime.Now);
}
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "存储", key);
}
}
public static void Add<T>(string key, T value, TimeSpan slidingExpiration)
{
if (value == null)
{
return;
}
if (slidingExpiration.TotalSeconds <= 0)
{
Remove(key);
return;
}
try
{
if (pool != null)
{
using (var r = pool.GetClient())
{
if (r != null)
{
r.SendTimeout = 1000;
r.Set(key, value, slidingExpiration);
}
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "存储", key);
}
}
public static T Get<T>(string key)
{
if (string.IsNullOrEmpty(key))
{
return default(T);
}
T obj = default(T);
try
{
if (pool != null)
{
using (var r = pool.GetClient())
{
if (r != null)
{
r.SendTimeout = 1000;
obj = r.Get<T>(key);
}
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "获取", key);
}
return obj;
}
public static void Remove(string key)
{
try
{
if (pool != null)
{
using (var r = pool.GetClient())
{
if (r != null)
{
r.SendTimeout = 1000;
r.Remove(key);
}
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "删除", key);
}
}
public static bool Exists(string key)
{
try
{
if (pool != null)
{
using (var r = pool.GetClient())
{
if (r != null)
{
r.SendTimeout = 1000;
return r.ContainsKey(key);
}
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "是否存在", key);
}
return false;
}
public static IDictionary<string, T> GetAll<T>(IEnumerable<string> keys) where T : class
{
if (keys == null)
{
return null;
}
keys = keys.Where(k => !string.IsNullOrWhiteSpace(k));
if (keys.Count() == 1)
{
T obj = Get<T>(keys.Single());
if (obj != null)
{
return new Dictionary<string, T>() { { keys.Single(), obj } };
}
return null;
}
if (!keys.Any())
{
return null;
}
IDictionary<string, T> dict = null;
if (pool != null)
{
keys.Select(s => new
{
Index = Math.Abs(s.GetHashCode()) % readHosts.Length,
KeyName = s
})
.GroupBy(p => p.Index)
.Select(g =>
{
try
{
using (var r = pool.GetClient(g.Key))
{
if (r != null)
{
r.SendTimeout = 1000;
return r.GetAll<T>(g.Select(p => p.KeyName));
}
}
}
catch (Exception ex)
{
string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "获取", keys.Aggregate((a, b) => a + "," + b));
}
return null;
})
.Where(x => x != null)
.ForEach(d =>
{
d.ForEach(x =>
{
if (dict == null || !dict.Keys.Contains(x.Key))
{
if (dict == null)
{
dict = new Dictionary<string, T>();
}
dict.Add(x);
}
});
});
}
IEnumerable<Tuple<string, T>> result = null;
if (dict != null)
{
result = dict.Select(d => new Tuple<string, T>(d.Key, d.Value));
}
else
{
result = keys.Select(key => new Tuple<string, T>(key, Get<T>(key)));
}
return result
.Select(d => new Tuple<string[], T>(d.Item1.Split('_'), d.Item2))
.Where(d => d.Item1.Length >= 2)
.ToDictionary(x => x.Item1[1], x => x.Item2);
}
}
}
C# redis使用之ServiceStack的更多相关文章
- Redis分布式锁(ServiceStack.Redis实现)
1.设计思路 由于Redis是单线程模型,命令操作原子性,所以利用这个特性可以很容易的实现分布式锁.A用户端在Resdis写入1个KEY,其他的用户无法写入这个KEY,实现锁的效果.A用户使用完成后释 ...
- ServiceStack.Redis订阅发布服务的调用(Z)
1.Redis订阅发布介绍Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息.类似于设计模式中的观察者模式.发布者和订阅者之间使用频 ...
- ServiceStack.Redis订阅发布服务的调用
1.Redis订阅发布介绍 Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息.类似于设计模式中的观察者模式. 发布者和订阅者之间使用频 ...
- ServiceStack.Redis 使用
Redis官网提供了很多开源的C#客户端.例如,Nhiredis ,ServiceStack.Redis ,StackExchange.Redis等.其中ServiceStack.Redis应该算是比 ...
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现
ASP.NET MVC 学习笔记-2.Razor语法 1. 表达式 表达式必须跟在“@”符号之后, 2. 代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...
- 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用
责任链模式的具体应用 1.业务场景 生产车间中使用的条码扫描,往往一把扫描枪需要扫描不同的条码来处理不同的业务逻辑,比如,扫描投入料工位条码.扫描投入料条码.扫描产出工装条码等,每种类型的条码位数 ...
- 使用ServiceStack构建Web服务
提到构建WebService服务,大家肯定第一个想到的是使用WCF,因为简单快捷嘛.首先要说明的是,本人对WCF不太了解,但是想快速建立一个WebService,于是看到了MSDN上的这一篇文章 Bu ...
- ASP.NET Redis 开发
文件并发(日志处理)--队列--Redis+Log4Net Redis简介 Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高 ...
- StackExchange.Redis通用封装类分享(转)
阅读目录 ConnectionMultiplexer 封装 RedisHelper 通用操作类封 String类型的封装 List类型的封装 Hash类型的封装 SortedSet 类型的封装 key ...
随机推荐
- [stm32] NRF24L01+USART搞定有线和无线通信
前言 一般进行远程监控时,2.4G无线通信是充当远程数据传输的一种方法.这时就需要在现场部分具备无线数据发送装置,而在上位机部分由于一般只有串口,所以将采集到的数据送到电脑里又要在上位机端设计一个数据 ...
- Canny算子边缘检测(cvCanny)
Canny是常用的边缘检测方法,其特点是试图将独立边的候选像素拼装成轮廓. John Canny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法. ...
- Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
Microsoft Dynamics CRM 2013 BTW: RC stands for Release for Candidate, and RTM stands for Release ...
- IOS 多线程01-线程基础知识
大部分现代操作系统,包括IOS,都支持执行线程的概念.每个进程可以包含多个线程,他们可以同时运行.如果只有一个处理器核心,操作系统将在所有执行线程之间切换,非常类似于在所有执行线程之间切换.如果拥有多 ...
- 前端chrome浏览器调试总结
引言 "工欲善其事,必先利其器" 恩,这句话我觉得说的特别有道理,举个例子来说吧,厉害的化妆师都有一套非常专业的刷子,散粉刷负责定妆,眼影刷负责打眼影,各司其职,有了专业的工具才能 ...
- SqlServer 错误1053:服务并未及时响应启动或控制请求
sqlserver 的登录用户修改成域账户后,启动不了 解决方法: 计算器管理选择管理员组 将域账户加入到管理员组即可
- ELK日志应用平台搭建
ELK架构: ElasticSearch:用于存储.索引日志. Logstash:用于收集.处理和转发事件或日志信息的工具. Kibana:搜索和可视化的日志的WEB界面. ELK优点: a.处理方式 ...
- Jenkins的系统设置
1.登录Jenkins进入以下界面: 2.点击 系统管理 3.点击 系统设置 (下图的系统设置是已经设置好的) 4.这里设置主要设置 Jenkins URL (这里我是测试的所以使用默认的)与 邮件的 ...
- 那些年我们写过的T-SQL(上篇)
在当今这个多种不同数据库混用,各种不同语言不同框架融合的年代(一切为了降低成本并高效的提供服务),知识点多如牛毛.虽然大部分SQL脚本可以使用标准SQL来写,但在实际中,效率就是一切,因而每种不同厂商 ...
- StringUtils 的用法
1.public static boolean isEmpty(String str) 判断某字符串是否为empty,标准是 null == str 或 str.length() == 0 2.pub ...