从hiredis使用出core谈谈redis多线程的使用
2014-11-17 20:20
489 查看
转自:http://my.oschina.net/jungleliu0923/blog/202948
摘要 hireedis多线程出core原因
目录[-]
1、情景描述
1.1 使用场景
1.2 初步实现方案
1.3 结果
2、线下复现
2.1 代码
2.2 编译执行
2.3 原因分析
3. 终极解决方案
在实际工作中,我需要使用redis的客户端去连接redis,于是选择了hiredis客户端(公司强推)。 hiRedis 是 Redis 官方指定的 C 语言客户端开发包,支持 Redis 完整的命令集、管线以及事件驱动编程。
线上出core如下:
?
当时经过多次尝试。把连接放入到了每个线程中。那么就不会出core了。
因为不方便公开公司代码,所以我写一个类似的代码来复现这个case。
-n [num] -h [host] -p [port], n为host数目,多个host用"-"进行分割。
testredis.cpp
?
Makefile
?
可以看到出core了
?
虽然出core位置不一致,但是经过查看代码,出core的原因应该是一致的。
?
可以看到的确在1152行对c->obuf进行了一次free导致出core。
我们分析下调用关系,首先调用redisCommand.
?
然后调用redisvCommand
?
接着调用redisvAppendCommand
?
这里,我们需要care调用__redisAppendCommand.
?
问题出现了。
对于任意一个多线程,他传入的redisContext* c都是一个,那么他们也公用同一个c->obuf,这里很明显,线程数据是耦合的。
当一个线程调用sdsfree c->obuf,其他任意一个线程使用c->obuf都会导致出core. 这也是我所谓的hiredis对多线程支持的不好的地方。
那么,如果我一定要在多线程中通过hiredis客户端调用redis呢。有没有方案了,答案肯定是有,只不过性能稍差。
原先的做法是先获得hiredis连接句柄,然后把句柄传入到多线程中,让多线程使用。现在改成在线程里面连接获得hiredis句柄,然后再进行使用。当然,代价是对于每个请求,都需要去连接redis服务器,加大了网络开销的同时还加大了redis的请求。
redis是单线程异步模型,hiredis这个客户端看来也只支持单线程。希望后续有redis的相关程序猿来改进相应问题,在hiredis使用多线程需要慎重。
摘要 hireedis多线程出core原因
目录[-]
1、情景描述
1.1 使用场景
1.2 初步实现方案
1.3 结果
2、线下复现
2.1 代码
2.2 编译执行
2.3 原因分析
3. 终极解决方案
在实际工作中,我需要使用redis的客户端去连接redis,于是选择了hiredis客户端(公司强推)。 hiRedis 是 Redis 官方指定的 C 语言客户端开发包,支持 Redis 完整的命令集、管线以及事件驱动编程。
1、情景描述
1.1 使用场景
一个epool模型的服务器不断接受外界请求,这个服务器框架给用户预留一个回调函数(多线程),回调函数为用户自己去实现的业务逻辑,其中redis的使用就需要在这个回调函数内部实现。1.2 初步实现方案
在程序启动的时候,我就初始化redis的连接,获得hiredis句柄。然后把hiredis句柄传入到线程函数里面。让其做相应的业务逻辑。1.3 结果
很不幸,一次请求都没问题,做压力测试,同时开20个线程访问,程序立即出core。线上出core如下:
?
2、线下复现
因为不方便公开公司代码,所以我写一个类似的代码来复现这个case。2.1 代码
代码主要有testredis.cpp和Makefile(自己指定hiredis目录)。用法是 ./redis-n [num] -h [host] -p [port], n为host数目,多个host用"-"进行分割。
testredis.cpp
?
?
2.2 编译执行
??
2.3 原因分析
从堆栈5可以看到 hiredis.c的1162行出的core,打开hiredis.c?
我们分析下调用关系,首先调用redisCommand.
?
?
?
?
对于任意一个多线程,他传入的redisContext* c都是一个,那么他们也公用同一个c->obuf,这里很明显,线程数据是耦合的。
当一个线程调用sdsfree c->obuf,其他任意一个线程使用c->obuf都会导致出core. 这也是我所谓的hiredis对多线程支持的不好的地方。
3. 终极解决方案
那么,如果我一定要在多线程中通过hiredis客户端调用redis呢。有没有方案了,答案肯定是有,只不过性能稍差。原先的做法是先获得hiredis连接句柄,然后把句柄传入到多线程中,让多线程使用。现在改成在线程里面连接获得hiredis句柄,然后再进行使用。当然,代价是对于每个请求,都需要去连接redis服务器,加大了网络开销的同时还加大了redis的请求。
redis是单线程异步模型,hiredis这个客户端看来也只支持单线程。希望后续有redis的相关程序猿来改进相应问题,在hiredis使用多线程需要慎重。
相关文章推荐
- 从hiredis使用出core谈谈redis多线程的使用
- 从hiredis使用出core谈谈redis多线程的使用【转】
- 【转】redis C接口hiredis 简单函数使用介绍
- 使用Redis客户端hiredis遇到的一些问题
- Asp.net Core 使用Redis存储Session
- C++使用hiredis连接带密码的redis服务
- 详解Asp.net Core 使用Redis存储Session
- CoreData 多线程下NSManagedObjectContext的使用
- CoreData的使用/以及coreData中的多线程问题/版本迁移(二)
- Asp.net Core 使用Redis存储Session
- asp.net core 使用 Redis 和 Protobuf
- ASP.NET CORE CACHE的使用(含MemoryCache,Redis)
- Redis客户端连接方式Hiredis简单封装使用,连接池、屏蔽连接细节
- 使用hiredis提供的接口访问redis中的ZSeT对象
- windows下redis 和 hiredis的编译与使用
- CoreData的使用以及coreData中的多线程问题
- 多线程在Core Data中的使用
- 多线程环境中使用redis
- [转] Hiredis: redis c client使用注记
- Asp.net Core 使用Redis存储Session