分布式锁

在并发编程中,经常会遇到多个线程访问同一个共享资源而这时候/我们就需要保证数据的“致性,那么就要用到锁的概念,给资源加上锁,拿到锁所有权的人才能够进行操作共享资源,没有拿到资源的线程需要等待,等其他线程使用完,释放锁。 在项目中,遇到多个用户抢购商品时、商品的数量就是共享资源。因此,在操作商品库存数据时,也需要使用锁保证商品库存的一致。 线程锁 如果在单服务器架构中,就可以使用线程锁保证数据的一致性。但是,此种方案不适合多服务器架构。 假设服务器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, ...
2023年10月04日

主键约束和唯一性约束的区别

主键必然是唯一且不为空,但是唯一不一定是主键,而且主键只能有一个,但是唯一约束仅仅是为了保持某些列具有唯一性而已。所以可以有多列 一张表里只能有一个主键约束,可以有多个唯一约束 主键约束的字段不能为null,而唯一约束的字段可以为null值 主键约束(PRIMARY KEY) 主键用于唯一地标识表中的每一条记录,可以定义一列或多列为主键。 是不可能(或很难)更新. 主键列上没有任何两行具有相同值(即重复值),不允许空(NULL). 主健可作外健,唯一索引不可; 唯一性约束(UNIQUE) 唯一性约束用来限制不受主键约束的列上的数据的唯一性,用于作为访问某行的可选手段,一个表上可以放置多个唯一性约束. 只要唯一就可以更新. 即表中任意两行在 指定列上都不允许有相同的值,允许空(NULL). 一个表上可以放置多个唯一性约束
2023年10月04日

Mysql中的Decimal类型说明

我们在Mysql中存字段的时候,比如,一些与金钱有关的数据。这个时候就会对精确到的要求非常高。那么这个时候,就会发现我们之前所学的八大基本类型不再能够满足需求,无论是整形还是浮点型,有人会说存整形有什么不可,但是你要知道不是每个人的金额都是整数的;这样不行的话,存浮点型的就可以了嘛,对于银行存钱来说,一个小数点的问题都会将一笔钱的金额变得很大或者很小......So,这个时候你可以尝试一下Decimal类型,你会发现能够很好地解决你的问题。 decimal详细介绍: decimal(a,b) 参数说明: a:指定小数点左边和右边可以存储的十进制数字的最大个数,最大精度为38. b:指定小数点右边可以存储的十进制数字的最大个数。小数位数必须是从0~a之间的值,默认小数位数是0. 举例说明,11615.23653234568这个数存你说的三个格式 decimal:11615 decimal(3):999 decdimal(3,2):9.99 decimal(10,5)11615.23653 超出精度范围的数会被强制进位并只显示数据类型定义的格式 备注: decimal数据类型用于要求非常高的精确计算中,这些类型允许指定数值的精确度和计算方法作为选择参数。精确度在这里指为这个值保存的有效数字的总个数。而计数方法指的是小数点后数字的个数。例如:decimal(5,2)规定了存储的值将不会超过五位数字 ,而且小数点后面有两位数字。 实例1: mysql> create table t1(c1 float(10,2), c3decimal(10,2)); Query OK, 0 rows affected (0.02 sec) mysql> insert into t1 values(9876543.21, 9876543.12); Query OK, 1 row affected (0.00 sec) mysql> select * from t1; +------------+------------+ | c1 | c3 | +------------+------------+ | 9876543.00 | 9876543.12 | +------------+------------+ 1 row in set (0.00 sec) 会发现,flocat类型的字段会自动将值四舍五入,而decimal类型的不会,如果用flocat类型的去存与金额有关的数据的时候就会出现问题,而decimal类型的就不会。 实例2:decimal(5,2) mysql> create table t1(id1 float(5,2) default null,id2 double(5,2) default ...
2023年10月04日