在并发编程中,经常会遇到多个线程访问同一个共享资源而这时候/我们就需要保证数据的“致性,那么就要用到锁的概念,给资源加上锁,拿到锁所有权的人才能够进行操作共享资源,没有拿到资源的线程需要等待,等其他线程使用完,释放锁。 在项目中,遇到多个用户抢购商品时、商品的数量就是共享资源。因此,在操作商品库存数据时,也需要使用锁保证商品库存的一致。 线程锁 如果在单服务器架构中,就可以使用线程锁保证数据的一致性。但是,此种方案不适合多服务器架构。 假设服务器1上使用线程锁保证同一时刻只有1个用户操作数据,却无法保证其他服务器上同时不能有用户操作,仍然会产生资源竞争。 因此,在多服务器架构中,不能使用线程锁的机制。 分布式锁 在上面的情况中,锁是分布在每个服务器上的。因此,不能保证所有服务器间数据的一致性。 想一想,可以将锁独立于各个服务器之外吗? 答案是肯定的,这就是分布式锁。 当确定了不同节点服务器之间需要分布式锁,那么我们就需要确定分布式锁到底有哪些功能? 互斥性:和本地锁一样,互斥性是最基本的,但是分布式锁需要保证在不同节点不同线程的互斥。 可重入性:同一个节点同一个线程如果获取了锁之后,那么也可以再次获取这个锁。 锁超时:和本地锁一样,支持锁超时,防止死锁。 高效、高可用:加锁和解锁需要高效,同时也需要保证高可用,防止分布式锁失效。 常见的分布式锁实现方式:MySQL、Redis等 MySQL锁 通过MySQL实现分布式锁,有两种方式:悲观锁和乐观锁。 悲观锁 概念 悲观锁是基于一种悲观的态度来防止一切数据冲突。它是以一种预防的姿态在修改数据之前把数据锁住,然后再对数据读写,在它释放锁之前,其他任何人不能对数据操作,直到前一个人把锁释放后,下一个人才对数据进行加锁,然后进行数据操作。 一般的关系型数据库管理系统中,锁的机制都是基于悲观锁的机制实现的。 特点:可以完全保证数据的独占性和正确性,因为每次请求都会对数据进行加锁,然后进行数据操作,最后再解锁,而加锁解锁的过程会造成服务器性能消耗。因此,在高并发的情况下,用MySQL实现分布式锁,毫无疑问是不行的!!! 只是了解MySQL实现分布式锁的思想即可。 自定义锁表实现 首先,需要创建一个有关资源的锁记录表: CREATE TABLE resourceLock( id INT UNSIGNED PRIMARY KEY AUTO_NCREMENT, resource_name VARCHAR(128) NOT NULL UNIQUE DEFAULT '' COMMENT '资源名字', node_info VARCHAR(128) DEFAULT NUUL COMMENT '机器信息', count INT UNSIGNED NOT NULL DEFAULT O COMMENT '锁的次数,实现重入性', desc_info VARCHAR(128) DEFAULT NULL COMMENT '额外的信息', update_time TIMESTAMP DEFAULT NULL COMMENT'更新时间', create_time TIMESTAMP DEFAULT NULL COMMENT '创建时间' )ENGINE=INNODB DEFAULT CHARSET=utf8; 定义锁的工具类 import time from django.db import connection, transaction class MysqlLock(object): def lock(self, ...