首页 新闻 会员 周边 捐助

ServiceStack.Redis连接池问题

0
悬赏园豆:10 [已解决问题] 解决于 2015-01-22 15:57

最近使用Redis,因为网站本身有资源缓存,如果我一更新,资源会全部重新请求刷新,可能瞬间的并发请求达到上万,然后Redis直接报“Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled in use

我设置的是1000个线程读写,还能继续设置更多还是说要手动释放连接?我有用using,但没用,

我本机模拟不出来同时1000个线程以上的并发,如果测试环境也不会报这个错

班级中队长的主页 班级中队长 | 初学一级 | 园豆:94
提问于:2015-01-22 12:31
< >
分享
最佳答案
0

增加 timeout 的值。

1000 个线程读写毫无意义,这会严重的降低系统的性能,你应该从策略上控制这样的事情发生,比如使用队列,或者将缓存资源的更新错开来。

收获园豆:10
Launcher | 高人七级 |园豆:45050 | 2015-01-22 12:37

我是要做集群的,可现在我第一台服务器都更新不上去,因为一更新IIS里的Redis就宕了,噢 你的意思是更新资源也用队列?我的IIS里报Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled in use这个错误之后,就一直恢复不过来,只有重启IIS才能正常。。。

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 12:40

@小季同学: 你的结构是不是这样的:你将 Redis 部署在机器 A 的 IIS 中,然后在客户端 B 中运行了一个测试程序,此程序通过 1000 个线程模拟从机器 A 读取和写入数据。对吗?

Launcher | 园豆:45050 (高人七级) | 2015-01-22 12:46

@Launcher: 我的结构是一台A服务器是正式环境的,一台Centos的Redis,一台B服务器测试的,测试都OK,然后网站程序更新到A服务器,就连接池耗尽了,我是要先更新A,然后加上负载,在接入B

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 12:54

@小季同学: 让我们用程序员能看懂的方式再把你的场景复述一遍。

1、机器 A 安装 CentOS,部署 Redis;

2、机器 B 为测试服务器,测试逻辑的实现大概是使用 1000 个线程模拟负载,使用 ServiceStack.Redis 作为客户端同时向机器 A 发起写入和读取请求;

3、不知道写啥了?还请你把“然后网站程序更新到A服务器...” 这句话用我上面的方式给解释清楚。

Launcher | 园豆:45050 (高人七级) | 2015-01-22 12:59

@Launcher: 三台服务器A、B、C

A和B都是Web服务器,C是Redis

A是正式服务器,在使用

B是测试的,二者都访问Redis

测试B是测试了程序的正确性,测试OK

计划是更新程序到A,然后加负载,在接入B,这样A和B来负载请求

实际是程序更新到A,瞬间并发过大,A扛不住

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 13:02

@小季同学: 你这表达能力欠佳啊,我再直观点猜一下你想表达的意思:

实际是程序更新到A -> 使用新的程序集覆盖,A 的应用程序池卸载,然后收到请求后启动,在启动的过程中会做一些初始化工作向 C 机器的 Redis 发送请求;

是这意思么?

Launcher | 园豆:45050 (高人七级) | 2015-01-22 13:08

@Launcher: 嗯 是的

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 13:09

@小季同学: 那么向 Redis 服务器发起请求的操作是因为用户请求所致,还是你的 A 服务上内在逻辑所致(比如,启动时会更新 Redis 中的一些数据)?

Launcher | 园豆:45050 (高人七级) | 2015-01-22 13:11

@Launcher: 用户请求的,因为本来A服务器缓存的有些数据,当更新重启的时候,用户会检测发现没有数据就会重新请求,这会的请求都集中起来了,正常的时候是有间隔的

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 13:17

@小季同学: 给段代码演示下你如何使用 ServiceStack.Redis 的。

Launcher | 园豆:45050 (高人七级) | 2015-01-22 13:41

@Launcher: 

using (var redis = prcm.GetClient().GetTypedClient<T>())
{
  redis.SetEntry(key, t, new TimeSpan(0, 10, 0));
}

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 13:53

@小季同学: 你这个连接池的 timeout 设置的是多少?

Launcher | 园豆:45050 (高人七级) | 2015-01-22 13:56

@Launcher: 应该是默认值2000毫秒吧,我没有另外设置,我写入的数据对象都是字节不多的

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 13:57

@小季同学: 我不知道你的使用方式是否用到了连接池模式(http://www.tuicool.com/articles/NbQrA3),你可以用抓包工具分析下 tcp 连接。

我假设你的设置是 100 个连接,连接超时为 2 秒,那么你遇到的问题就是目前有 100 个连接都正在使用,而且超过 2 秒后仍然没有机会得到空闲的连接。造成此问题的原因有两个,正在处理的客户请求太多,读写 Redis 耗时。你可能需要先排查后一个问题,有可能是 Redis 服务器负载过高,或者带宽不足等原因引起。但是,最终你还是要做一件事情,就是将用户请求异步化,通过队列处理 Redis 请求,每Redis 客户端有两条连接就足够了。

Launcher | 园豆:45050 (高人七级) | 2015-01-22 14:21

@Launcher: 明白了,谢谢,我改成队列的方式

班级中队长 | 园豆:94 (初学一级) | 2015-01-22 15:57
其他回答(1)
0

你好,问个问题,在实用redis的master/slave模式时,同步延迟是怎么解决的?

还有,如果我使用redis的连接池,问什么每次获取到的客户端的info信息都是一样的,而不是随着key的更新而更新。

谢谢。

rana4504 | 园豆:214 (菜鸟二级) | 2015-10-10 15:46
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册