订单分表和redis分布式锁的实现,数据库innodb3种锁的实现


学习了淘宝的订单系统设计,将订单拆分为买家库、卖家库,消息中间件进行订单同步(类似于方案1、2的对买家、卖家分表么),似乎是不关注订单数据冗余,但没想明白如何按照订单查询,所以借鉴设计了方案3:
(1)按照userId取模分表
(2)按照sellerId取模分表
(3)按照orderId取模分表
相比方案1、2,少维护了一张表,但有两份数据冗余


订单水平分库分表,为什么要按照用户id来切分呢?


好处:查询指定用户的所有订单,避免了跨库跨表查询。
因为,根据一个用户的id来计算节点,用户的id是规定不变的,那么计算出的值永远是固定的(x库的x表)
那么保存订单的时候,a用户的所有订单,都是在x库x表里面。需要查询a用户所有订单时,就不用进行跨库、跨表去查询了。


建立一个索引关系表,暂且叫做订单用户关系索引表order_user_idx
存储的数据包括两项:订单号、用户编号。
 

32个库,每个库32个表,总共是1024张表,每个库正常承载的写入并发量是1000,那么32个库就可以承载32*1000=32000的写并发,如果每个库承载1500的写并发,32*1500=48000 的写并发,接近5万每秒的写入并发,前面再加一个MQ削峰,每秒写入MQ8万条数据,每秒消费5万条数据。1024张表,假设每个表存放500万数据,在MYSQL里可以放50亿条数据

路由的规则:orderId 模 32 = 库,orderId/32 模 32 = 表


IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用层。
TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP协议是应用层协议,主要解决如何包装数据


socket是对TCP/IP协议的封装,它的出现只是使得程序员更方便地使用TCP/IP协议栈而已


HTTP是轿车,提供了封装或者显示数据的具体形式;
Socket是发动机,提供了网络通信的能力。
 

====== redis 分布式锁实现===============
$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期
$lock = $redis->setnx($key, $value);
//判断是否上锁成功,成功则执行下步操作
if(!empty($lock))
{
     //下步操作...       
}
如果返回 1 ,则表示当前进程获得锁,并获得了当前插入/更新缓存的操作权限。
如果返回 0,表示锁已被其他进程获取,这是进程可以返回结果或者等待当前锁失效再请求。


解决方法是在获取锁失败的同时获取锁的值,并将值与当前时间进行对比,如果值小于当前时间说明锁以过期失效,进程可运用Redis的DEL命令删除该锁。


GETSET命令在给锁设置新值的同时返回锁的旧值,这里利用了GETSET命令同时获取和赋值的特性,在此期间其他进程无法修改锁的值。
 

InnoDB中有三种行锁技术:

Record Lock:单个行记录上的锁,我们通常讲的行锁,它的实质是通过对索引的加锁实现;只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。在事务隔离级别为读已提交下,仅采用Record Lock。


Gap Lock:间隙锁,锁定一个范围,但不包含记录本身;


Next-Key Lock:Record Lock+Gap Lock,锁定一个范围,并且锁定记录本身

对查询范围进行加锁,在另一个事务执行插入操作时是不被运行的,从而避免了幻读

MVCC的实现
为了实现MVCC,innodb对每一行都加上两个隐含的列,其中一列存储行被更新的时间,另外一列存储行被删除的时间。但是innodb存储的并不是绝对的时间,而是与时间对应的数据库系统的版本号。(保存这两个额外系统版本号使大多数读操作可以不加锁)

每当一个事务开始的时候,innodb都会给这个事务分配一个递增的版本号。所以版本号也可以被认为是事务号。

对于每一个查询语句,innodb都会把这个查询语句的版本号同查询遇到的行的版本号进行对比,然后结合不同的事务等级来决定是否返回该行。
select语句实现
Innodb只查找版本号早于当前事务版本的数据号(包括等于)。这样可以确保事务读取的行要么是事务开始前已经存在的,要么是事务自身插入或修改的。

行的删除版本号,要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行在事务开始之前未被删除。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值