在我们做多进程应用开发的过程中,难免会遇到多个进程访问同一个资源(临界资源)的状况,必须通过加一个全局性的锁,来实现资源的同步访问(同一时间只能有一个进程访问资源)。

举个例子:

假设我们用mysql来实现一个任务队列,实现的过程如下:

1. 在Mysql中创建Job表,用于储存队列任务,如下:

create table jobs(

id auto_increment not null primary key,

message text not null,

job_status not null default 0

);

message 用来存储任务信息,job_status用来标识任务状态,假设只有两种状态,0:在队列中, 1:已出队列

2. 有一个生产者进程,往job表中放新的数据,进行排队

insert into jobs(message) values(‘msg1‘);

3.假设有多个消费者进程,从job表中取排队信息,要做的操作如下:

select * from jobs where job_status=0 order by id asc limit 1;

update jobs set job_status=1 where id = ?; -- id为刚刚取得的记录id

4. 如果没有跨进程的锁,两个消费者进程有可能同时取到重复的消息,导致一个消息被消费多次。这种情况是我们不希望看到的,于是,我们需要实现一个跨进程的锁。

这里我贴出非常好的一篇文章,大家可以参照一下:

https://blog.engineyard.com/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you

=========================华丽的分割线=======================================

说道跨进程的锁实现,我们主要有几种实现方式:

1. 信号量

2. 文件锁fcntl

3. socket(端口号绑定)

4. signal

这几种方式各有利弊,总体来说前2种方式可能多一点,这里我就不详细说了,大家可以去查阅资料。

查资料的时候发现mysql中有锁的实现,适用于对于性能要求不是很高的应用场景,大并发的分布式访问可能会有瓶颈,链接如下:

http://dev.mysql.com/doc/refman/5.0/fr/miscellaneous-functions.html

我用python实现了一个demo,如下:

文件名:glock.py

#!/usr/bin/env python2.7

#

# -*- coding:utf-8 -*-

#

# Author : yunjianfei

# E-mail : [email protected]

# Date : 2014/02/25

# Desc :

#

import logging, time

import MySQLdb

class Glock:

def __init__(self, db):

self.db = db

def _execute(self, sql):

cursor = self.db.cursor()

try:

ret = None

cursor.execute(sql)

if cursor.rowcount != 1:

logging.error("Multiple rows returned in mysql lock function.")

ret = None

else:

ret = cursor.fetchone()

cursor.close()

return ret

except Exception, ex:

logging.error("Execute sql \"%s\" failed! Exception: %s", sql, str(ex))

cursor.close()

return None

def lock(self, lockstr, timeout):

sql = "SELECT GET_LOCK(‘%s‘, %s)" % (lockstr, timeout)

ret = self._execute(sql)

if ret[0] == 0:

logging.debug("Another client has previously locked ‘%s‘.", lockstr)

return False

elif ret[0] == 1:

logging.debug("The lock ‘%s‘ was obtained successfully.", lockstr)

return True

else:

logging.error("Error occurred!")

return None

def unlock(self, lockstr):

sql = "SELECT RELEASE_LOCK(‘%s‘)" % (lockstr)

ret = self._execute(sql)

if ret[0] == 0:

logging.debug("The lock ‘%s‘ the lock is not released(the lock was not established by this thread).", lockstr)

return False

elif ret[0] == 1:

logging.debug("The lock ‘%s‘ the lock was released.", lockstr)

return True

else:

logging.error("The lock ‘%s‘ did not exist.", lockstr)

return None

#Init logging

def init_logging():

sh = logging.StreamHandler()

logger = logging.getLogger()

logger.setLevel(logging.DEBUG)

formatter = logging.Formatter(‘%(asctime)s -%(module)s:%(filename)s-L%(lineno)d-%(levelname)s: %(message)s‘)

sh.setFormatter(formatter)

logger.addHandler(sh)

logging.info("Current log level is : %s",logging.getLevelName(logger.getEffectiveLevel()))

def main():

init_logging()

db = MySQLdb.connect(host=‘localhost‘, user=‘root‘, passwd=‘‘)

lock_name = ‘queue‘

l = Glock(db)

ret = l.lock(lock_name, 10)

if ret != True:

logging.error("Can‘t get lock! exit!")

quit()

time.sleep(10)

logging.info("You can do some synchronization work across processes!")

##TODO

## you can do something in here ##

l.unlock(lock_name)

if __name__ == "__main__":

main()

在main函数里, l.lock(lock_name, 10) 中,10是表示timeout的时间是10秒,如果10秒还获取不了锁,就返回,执行后面的操作。

在这个demo中,在标记TODO的地方,可以将消费者从job表中取消息的逻辑放在这里。即分割线以上的:

3.假设有多个消费者进程,从job表中取排队信息,要做的操作如下:

select * from jobs where job_status=0 order by id asc limit 1;

update jobs set job_status=1 where id = ?; -- id为刚刚取得的记录id

这样,就能保证多个进程访问临界资源时同步进行了,保证数据的一致性。

测试的时候,启动两个glock.py, 结果如下:

Java代码  

[@tj-10-47 test]# ./glock.py

2014-03-14 17:08:40,277 -glock:glock.py-L70-INFO: Current log level is : DEBUG

2014-03-14 17:08:40,299 -glock:glock.py-L43-DEBUG: The lock ‘queue‘ was obtained successfully.

2014-03-14 17:08:50,299 -glock:glock.py-L81-INFO: You can do some synchronization work across processes!

2014-03-14 17:08:50,299 -glock:glock.py-L56-DEBUG: The lock ‘queue‘ the lock was released.

可以看到第一个glock.py是 17:08:50解锁的,下面的glock.py是在17:08:50获取锁的,可以证实这样是完全可行的。

[@tj-10-47 test]# ./glock.py

2014-03-14 17:08:46,873 -glock:glock.py-L70-INFO: Current log level is : DEBUG

2014-03-14 17:08:50,299 -glock:glock.py-L43-DEBUG: The lock ‘queue‘ was obtained successfully.

2014-03-14 17:09:00,299 -glock:glock.py-L81-INFO: You can do some synchronization work across processes!

2014-03-14 17:09:00,300 -glock:glock.py-L56-DEBUG: The lock ‘queue‘ the lock was released.

[@tj-10-47 test]#

原文:http://blog.csdn.net/yun_jianfei/article/details/25369719

mysql跨进程锁_python基于mysql实现的简单队列以及跨进程锁相关推荐

  1. mysql项目案例电影_Python+Django+Mysql实现在线电影推荐系统 基于用户、项目的协同过滤推荐在线电影系统 代码实现 源代码下载...

    Python+Django+Mysql实现在线电影推荐系统(基于用户.项目的协同过滤推荐算法) pycharm2020professional版本,python3.8版本,django3.1.1版本, ...

  2. mysql php 新手卡生成_PHPMaker(基于MYSQL数据库自动生成PHP 脚本的软件)

    PHPMaker 注册版是一款PHP代码自动生成工具,一款在Windows平台上运行的基于MYSQL数据库自动生成PHP脚本的软件.使用生成的PHP代码,你可以通过WEB网页 对数据库的记录进行浏览. ...

  3. mysql数据生产数据分析_基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程...

    基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程 课程目录 (1)SQL与数Ju分析;目录中文件数:23个 (1) 开课-课时3SQL与数Ju库的价值.flv (2) ...

  4. MySQL组复制学习笔记(基于MySQL 8+) -- 使用篇

    3.1. 启动/停止 可以通过start/stop group_replication来启动停止组复制进程. mysql> start group_replication; /* 启动MySQL ...

  5. mysql idataparameter_数据访问基础类(基于MYSQL)

    //Copyright (C) 2006-2010 Kolee///数据访问基础类(基于MYSQL)///publicclassMySqlHelper2 {publicMySqlHelper2() { ...

  6. 获取mysql所有用户权限_python 获取mysql数据库列表以及用户权限

    #!/usr/bin/env python#coding: utf-8 importjsonimportpymysqlclassMysql(object):#mysql 端口号,注意:必须是int类型 ...

  7. python mysql数据库长连接_python 连接mysql数据库

    python34之殇--DJango连接Mysql数据库 系统环境: 64位 windows 7 + python34 + Django 1.8 问题描述: 因为MySQLdb不兼容python3.x ...

  8. python怎么建立画板_Python基于opencv实现的简单画板功能示例

    本文实例讲述了Python基于opencv实现的简单画板功能.分享给大家供大家参考,具体如下: import cv2 import numpy as np drawing = False # true ...

  9. python jieba库分词_Python基于jieba库进行简单分词及词云功能实现方法

    本文实例讲述了Python基于jieba库进行简单分词及词云功能实现方法.分享给大家供大家参考,具体如下: 目标: 1.导入一个文本文件 2.使用jieba对文本进行分词 3.使用wordcloud包 ...

最新文章

  1. Heartrate:一个牛逼的工具,Python执行实时可视化
  2. GPS计算司机行车时长,深圳交警开启疲劳驾驶午间整治
  3. C# 容器重用避免GC 的论证
  4. elasticsearch Insert 插入数据和delete 删除数据(Java)
  5. webpack是什么?为什么要用webpack(一个小白的感想)
  6. 容器和虚拟机到底有啥区别?
  7. asp.net MVC初学体会.
  8. linux修改tomcat时间命令,Linux下把tomcat日志按日期自动分割
  9. hcia第五天 结课
  10. 大学生计算机考试PPT制作,计算机等级考试制作PPT表格
  11. 电脑可以上网但打不开微信公众号
  12. python 生成有效的四要素
  13. zabbix监控平台设置报警发送邮件
  14. 彻底删除aws亚马逊服务器使之不再计费
  15. 58同城一面【前端】
  16. 机器码怎么改?笔记本机器码怎么改?(最新你看你也会)
  17. 大数据使磁带重获新生
  18. AI 黑科技,老照片修复,模糊变高清
  19. STM32 HAL库学习笔记4-SPI
  20. java 静态区在jvm哪里,JDKJREJVM这三者的联系与区别///java跨平台///堆栈常量区静态区...

热门文章

  1. SAP Spartacus layout设计原理
  2. SAP Spartacus 自定义 Component 的使用 - SimpleResponsiveBannerComponent
  3. 如何查看类型为LRAW的SAP ABAP数据库表字段的内容
  4. every function in scala is an instance of a class
  5. CRM_DOC_FLOW_READ_DB debug
  6. Leo的AR代码学习之create-react-class
  7. sap-ui-core.js reference in Webclient ui
  8. ABAP webdynpro Dynamically add file upload
  9. 打印product所有attachment 具体信息的小工具
  10. 使用simple transformation查找xml file内某个节点的attribute是否存在指定value