免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123456789
最近访问板块 发新帖
楼主: csumck

[技术动态] 今天听说了腾讯一个很牛逼的技术, 求问是怎么实现的 [复制链接]

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-09-28 15:35 |显示全部楼层
这个是我以前的一个实现,  用select实现, 替换 mysql_real_query, 现在好像新版本的MYSQL client query, 已经增加了类似的代码,  默认就是非阻塞的了.
#include <iostream>
#include <string>
#include <mysql.h>
#include <error_message.hpp>

#ifndef _my_noblock_query_hpp
#define _my_noblock_query_hpp

int mysql_noblock_query(MYSQL *mysql, const char *query, ulong length)
{
   struct timeval tv1;
   fd_set recvfd;
   int  mysql_fd;
   int  ret;
   int int_err;
   std::string str_msg;

  if ( mysql_send_query( mysql,query,length ) )
     return 1;

   //用SELECT检测有没有数据到达mysql_fd
  mysql_fd = mysql->net.fd;
  FD_ZERO( &recvfd );
  FD_SET( mysql_fd , &recvfd );
  tv1.tv_sec=600;  // 最多检查600秒
  tv1.tv_usec=0;
  ret = select( mysql_fd+1, &recvfd, NULL, NULL, &tv1 );
  if( 0==ret )  {
       str_msg =  "Select time out. Query=";
       str_msg += query ;
       warning_message_str(str_msg);
       }
  else if( ret<0 )  {
       int_err = errno;
       str_msg =  "Select run bad. errno=";
       str_msg +=   std::to_string(int_err) ;
       str_msg +=   ", strerror=";
       str_msg +=  strerror( int_err ) ;
       warning_message_str(str_msg);
       }
  return  mysql_read_query_result(mysql);
}

#endif /* _my_noblock_query_hpp */

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-09-29 13:04 |显示全部楼层
本帖最后由 yulihua49 于 2015-09-29 13:37 编辑
wlmqgzm 发表于 2015-09-28 15:35
这个是我以前的一个实现,  用select实现, 替换 mysql_real_query, 现在好像新版本的MYSQL client query, 已 ...

嗯。看了一下。作为AIO例子,还不错。
但是,异步后在那等,就没有实际意义了,可以结合协程技术,释放线程。等事件到了再回来处理。

这方面,mysql就比ORACLE强了,OCI似乎没有开放内部连接。

  1. int mysql_noblock_query(MYSQL *mysql, const char *query, ulong length)
  2. {
  3.     int  ret;
  4.     int int_err;
  5.     std::string str_msg;

  6.    if ( mysql_send_query( mysql,query,length ) )
  7.       return 1;

  8.     //用epoll检测有没有数据到达mysql_fd,yield,and resume
  9.    ret=do_event(mysql->net.fd,0,600);//前后可千万不要有线程锁啊,回来的可不一定是原来的线程。

  10.        if( ret<0 )  {//出错后可以改同步
  11.            if( -11==ret )  {
  12.         str_msg =  "Select time out. Query=";
  13.         str_msg += query ;
  14.         warning_message_str(str_msg);
  15.         } else {//出错后可以改同步
  16.         int_err = errno;
  17.         str_msg =  "Select run bad. errno=";
  18.         str_msg +=   std::to_string(int_err) ;
  19.         str_msg +=   ", strerror=";
  20.         str_msg +=  strerror( int_err ) ;
  21.         warning_message_str(str_msg);
  22.         }
  23.         }
  24.    return  mysql_read_query_result(mysql);
  25. }
复制代码

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-10-02 16:58 |显示全部楼层
本帖最后由 wlmqgzm 于 2015-10-02 17:11 编辑

回复 82# yulihua49

也是不错的方案,  其实就是   到了mysql_send_query( mysql,query,length ) )这一步之后,  基本上各类异步IO调用的手段都可以, 可以结合项目的实际情况,
进行各种处理, 总之, 就是把CPU控制权交出去就行了, 无论是SELECT, EPOLL, POLL, 协程 等等都可以.

如果只涉及单条或者少量Mysql连接,  SELECT在这里是比EPOLL更好的方案,  SELECT会移交CPU, 也是最通用的方案,适应一切场合,最终用户直接调用就可以, 不需要了解内部,像平时的mysql_real_query一样使用就好了.
另外,由于SELECT函数的高效率,最新mysql的代码中, 所有"sleep(微秒)" 函数的调用, 也是直接用SELECT调用替换了.

当然, 使用 协程  也是更好的办法之一, 但是要麻烦一些,通用性没有这么好.
   

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-10-03 11:14 |显示全部楼层
本帖最后由 yulihua49 于 2015-10-03 11:38 编辑
wlmqgzm 发表于 2015-10-02 16:58
回复 82# yulihua49

也是不错的方案,  其实就是   到了mysql_send_query( mysql,query,length ) )这一步 ...

epoll也是会移交CPU的。
甚至,你就是采取同步操作,也是会移交CPU的。
好像sleep内部就是select。

使用协程,麻烦不止一点点。实在是太麻烦了,尤其是在C/C++。
在lua,go。。。。我弄不明白他们的resume条件是怎样设定的。我这里是由epoll决定的,yield时控制权交给epoll,激活后,得context,判定是个AIO的yield引起的,就resume。这期间如果该线程得到的是谁的context,就给谁干活。
所以,这个线程说不定给谁干活去了,也说不定哪个线程会给你resume。这个控制自然是非常非常的麻烦,还会出各种意想不到的问题。
我的接口看起来简单,就一个函数。在它背后,至少1000行代码在支援它的工作。
普通的协程,只在单线程工作,控制简单的多,但是不能发挥多核并行处理的优势。

我的模型,已经测试成功,可以应付socket和文件AIO的工作。oracle没有开放他的socket和回调函数,所以没办法协程。
mysql这个很好,我还没试过。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-10-05 09:45 |显示全部楼层
wlmqgzm 发表于 2015-09-28 15:35
这个是我以前的一个实现,  用select实现, 替换 mysql_real_query, 现在好像新版本的MYSQL client query, 已 ...


你的代码里最后一句mysql_read_query_result(mysql)   这里假如网络还没有读到足够的数据,是不是会阻塞的?

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-10-05 10:58 |显示全部楼层
本帖最后由 Charlie_gan 于 2015-10-08 10:30 编辑

回复 1# 小尾巴鱼


论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-10-12 19:37 |显示全部楼层
本帖最后由 wlmqgzm 于 2015-10-12 19:38 编辑

回复 85# csumck

在这里不会, 因为只有几字节的数据, 只是返回执行成功与否.

对于select返回大量数据的情况,  需要另外处理的地方是  mysql_store_result 这个函数.  这里要加SELECT或者类似的处理.


   

论坛徽章:
6
数据库技术版块每日发帖之星
日期:2015-11-27 06:20:00程序设计版块每日发帖之星
日期:2015-12-01 06:20:00每日论坛发贴之星
日期:2015-12-01 06:20:0015-16赛季CBA联赛之佛山
日期:2017-03-26 23:38:0315-16赛季CBA联赛之江苏
日期:2017-07-17 10:08:4415-16赛季CBA联赛之北京
日期:2018-03-04 17:01:50
发表于 2015-10-13 13:13 |显示全部楼层
嗯。看了一下,还不错。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP