根据gevent和pymysql完成mysql读写的异步非阻塞计划51CTO博客 - 千亿集团

根据gevent和pymysql完成mysql读写的异步非阻塞计划51CTO博客

2019年04月24日09时03分37秒 | 作者: 运良 | 标签: 阻塞,完成,进程 | 浏览: 2574

我们常常运用的mysql库,MySQL-Python库是用C写的,很惋惜它是阻塞的,要完成异步的MySQL驱动必须用Python版其他MySQL驱动!

现在社区里边有两个纯python完成的mysql驱动。一个是 myconnpy  另一个是PyMysql ~ 这两个mysql驱动文档适当的少呀,好在他们的用法和MySQldb适当的像,否则就要头疼的看代码了。。。 完成的方法是用socket来交互,不像mysqldb封装了libmysqlclient那样 !


myconnpy我国的tornado大牛引荐过,可是也点评过,形似有些bug的姿态。

我这边就用Mozilla公司 也在用的pymysql ~


我们先创立数据库和数据表

装置python的mysql模块~



PySQL针对mysql操作demo还算简略的~


import pymysql
db = pymysql.connect(host = localhost, passwd = 123123, user = root, db = rui)
cursor = db.cursor()
sql=select count(*) from kkk
data = cursor.execute(sql)
print cursor
cursor.close()
db.close()


其实我们也能够模仿apache那样prefork形式,来派生使命履行目标。

prefork选用预派生子进程方法,用独自的子进程来处理 不同的恳求,进程之间互相独立。我这边测验是mysql阻塞方法,我们也能够运用这种计划模仿多个使命履行。有点相似多进程的姿态,耗费比较大的~


#!/usr/bin/python
# -*- coding: utf-8 -*-
#xiaorui.cc
import MySQLdb, pymysql
import signal, os, sys
                                                                                                                                                                                                  
workers = {}
                                                                                                                                                                                                  
def run():
  con = MySQLdb.connect(host=localhost, db=rui, user=root, passwd=123123)
  signal.signal(signal.SIGTERM, lambda sig, status: sys.exit(0))
  cur = con.cursor()
  cur.execute("SELECT SLEEP(30)")
                                                                                                                                                                                                  
def killall(sig, status):
  for pid in workers.keys():
  os.kill(pid, signal.SIGTERM)
                                                                                                                                                                                                  
def waitall():
  for pid in workers.keys():
  try:
  os.waitpid(pid, 0)
  except:
  print "waitpid: interrupted exception"
                                                                                                                                                                                                  
def main():
  print os.getpid()
  signal.signal(signal.SIGTERM, killall)
  for i in range(3):
  pid = os.fork()
  if pid  0:
  try:
    run()
  except:
    print "run: interrupted exception"
    sys.exit(0)
  else:
  workers[pid] = 1
  waitall()
                                                                                                                                                                                                  
if __name__  __main__:
  main()


看到这三个sleep30都在跑吗? 看起来收效了,但三个进程仍是耗费了130秒。



好了说正题,今日怎样首要说的便是gevent和python下的mysql驱动测验,共享个gevent和pymysql的在一起运用的实例demo ~


def goodquery(sql):
  db = pymysql.connect(host = localhost, passwd = 123123, user = root, db= rui)
  cursor = db.cursor()
  data = cursor.execute(sql)
  cursor.close()
  db.close()
  return cursor
sqla=select count(*) from kkk
sqlb="select * from kkk where name like %888888%"
jobs = [gevent.spawn(goodquery, (sqla)),gevent.spawn(goodquery, (sqlb))]
#jobs = [gevent.spawn(goodquery, (sqla)),gevent.spawn(goodquery,(sqlb)),gevent.spawn(goodquery,(sqlb))]
gevent.joinall(jobs, timeout=2)
what_you_want = [job.value for job in jobs]
print what_you_want
for i in what_you_want:
  for a in i:
    print a




哎,仍是有点阻塞。。。 跑了6个耗时3s的sql,共用了18秒的时刻。。。。


通过一上午的折腾,得知gevent的版别没有用对,只要gevent 1.0 才完美支撑socket,然后需要在引进模块的后边,打上其他补丁!


gevent.monkey.patch_socket()


real  0m8.993s
user  0m0.071s
sys   0m0.016s


在这里我再测验下多线程的版别:

import pymysql
import threading
def goodquery(sql):
  db = pymysql.connect(host = localhost, passwd = 123123, user = root, db= rui)
  cursor = db.cursor()
  data = cursor.execute(sql)
  cursor.close()
  db.close()
  print cursor
  return cursor
sqla=select count(*) from kkk
sqlb="select * from kkk where name like %888888%"
#jobs = [gevent.spawn(goodquery,(sqla)),gevent.spawn(goodquery,(sqlb)),gevent.spawn(goodquery,(sqlb)),gevent.spawn(goodquery,(sqlb)),gevent.spawn(goodquery,(sqlb))]
#jobs = [gevent.spawn(goodquery, (sqla)),gevent.spawn(goodquery,(sqlb)),gevent.spawn(goodquery,(sqlb))]
#gevent.joinall(jobs, timeout=30)
#what_you_want = [job.value for job in jobs]
threads=[]
for i in range(5):                                      
  threads.append( threading.Thread( target=goodquery,args=(sqlb,) ) )
for t in threads:
  t.start()
for t in threads:
  t.join()


他的测验成果要比gevent慢点 ~但也是并发的履行,能够在mysql进程里边看到履行的记载 ~

[root@101 ~]# time python t.py
real  0m11.122s
user  0m0.095s
sys   0m0.026s


总结下:

       gevent pymysql 或者是 threading pymysql 是靠谱的~  是能够处理大数据下的mysql读写阻塞的问题的~    

       可是和sohu、腾讯的朋友评论了下我的这个计划,mysql阻塞是在与事务处理时发作的。 看来mysql的阻塞不是这么搞处理的,今后有环境后,会持续的追寻这事 ~

版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表千亿集团立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章