redis秒杀系统数据同步(保证不多卖)

2023-05-16

原文链接 http://www.cnblogs.com/shihaiming/p/6062663.html

东西不多卖

秒杀系统需要保证东西不多卖,关键是在多个客户端对库存进行减操作时,必须加锁。Redis中的Watch刚好可以实现一点。首先我们需要获取当前库存,只有库存中的食物小于购物车的数目才能对库存进行减。在高并发的情况下会出现某时刻查询库存够的,但下一时刻另外一个线程下单了,对库存进行减操作,刚好小于上个线程的购物车数目。照理现在的状态是不能下单成功的,因为库存已经不够了,但上一线程仍然认为数量还够,对库存进行减操作,从而导致库存出现负数的情况。如何避免?

Redis 中的watch可以在事务前对数据进行监控,如果在事务执行前,该数据发生改变,则事务不执行。刚好能满足我们的要求。看了很多代码,对watch功能还不是很理解,因为网上很多写的帖子都没有明确指出多客户端(理解之后发现还是有写的),所以不明白的可以参见下面的例子,是用Java写的。以下代码可以保证库存不多卖。

在redis中设置一个键为mykey,值为1000的变量,

public class Main {

    public static void main(String[] args) {
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
    }
}

class MyThread extends Thread {
    Jedis jedis = null;

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            System.out.println(Thread.currentThread().getName());
            jedis = RedisUtil.getJedis();
            try {
                int stock = Integer.parseInt(jedis.get("mykey"));
                if (stock > 0) {
                    jedis.watch("mykey");
                    Transaction transaction = jedis.multi();
                    transaction.set("mykey", String.valueOf(stock - 1));
                    List<Object> result = transaction.exec();
                    if (result == null || result.isEmpty()) {
                        System.out.println("Transaction error...");// 可能是watch-key被外部修改,或者是数据操作被驳回
                    }
                } else {
                    System.out.println("库存为0");
                    break;
                }
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                RedisUtil.returnResource(jedis);
            }finally{
                RedisUtil.returnResource(jedis);
            }

        }
    }

}

对于Redis事务来说行不通,因为在exec命令之前,所有的命令都被Redis缓存起来了,根本就拿不到balance的值。那类似这种需要基于已经存在的某个值的事务在Redis中如何实现呢?答案是Watch命令:

redis.watch('balance')
balance = redis.get('balance')
if (balance < amtToSubtract) {
    redis.unwatch()
} else {
    redis.multi()
    redis.decrby('balance', amtToSubtract)
    redis.incrby('debt', amtToSubtract)
    redis.exec()
}

通俗点讲,watch命令就是标记一个键,如果标记了一个键,在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中重新再尝试一次。像上面的例子,首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减;足够的话,就启动事务进行更新操作,如果在此期间键balance被其它人修改,那在提交事务(执行exec)时就会报错,程序中通常可以捕获这类错误再重新执行一次,直到成功。
Redis事务失败后不支持回滚 与数据库事务很重要的一个区别是Redis事务在执行过程中出错后不会回滚。在exec命令后,Redis Server开始一个个的执行被缓存的命令,如果其中某个命令执行出错了,那之前的命令并不会被回滚。

 

 

Redis保证从数据只加载一次

我这里碰到的需求是一开始要从MySQL数据库中导入数据到Redis,由于有多台服务器,不进行控制会对数据进行多次加载,所以我们可以设置一个键值进行控制。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
public class Main {

    public static void main(String[] args) {
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
            new lock().start();
    }
}

class lock extends Thread{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(Thread.currentThread().getName());
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            if(jedis.setnx("look", "1") == 1){
                jedis.set("food", Thread.currentThread().getName());
            }else{
                System.out.println(Thread.currentThread().getName() + "未访问");
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            RedisUtil.returnResource(jedis);
        }finally{
            RedisUtil.returnResource(jedis);
        }
    }

}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redis秒杀系统数据同步(保证不多卖) 的相关文章

  • ubuntu下用apt-get install 安装软件时出现 initramfs-tools错误

    错误提示 xff1a gzip stdout No space left on device E mkinitramfs failure cpio 141 gzip 1 update initramfs failed for boot in
  • ubuntu虚拟机下桥接模式,静态ip上网

    近期使用VM安装了ubuntu12 10玩玩 xff0c 途中也遇到了许多问题 xff0c 安装完成后 xff0c 系统默认是选择NAT连接方式的 xff0c 可以直接通过火狐浏览器上网 xff08 不需任何设置 xff0c 系统自己配置好
  • Windows下安装GTK+(整理)

    以下为网上摘的 xff0c 自己把它整理在了一起 WINDOWS下实现GTK 43 GTKMM的编程 xff08 一 xff09 下载软件包 1 下载dev C 43 43 开发软件 xff08 我的版本是4 9 9 2 xff09 2 下
  • windows gtk+开发环境搭建方法详解(图解)

    GTK 43 开发环境搭建 工欲善其事 必先利其器 首先介绍一下GTK 43 开发环境的搭建 网上很多所谓的GTK的开发环境的搭建基本都是抄来抄去 也不知道有没有人使用他们介绍的方法搭建并编译成功 很不幸的是我使用他们写的方法没有搭建成功
  • GTK在Linux下的安装

    linux gtk 是linux平台下的图形界面开发接口 xff0c 它不同于qt xff0c 它是完全免费的 xff0c Qt是基于c 43 43 的商业开发包 xff0c 涉及版权等问题 xff0c gtk则是基于c的全免费的 xff0
  • android SDK下各目录的用途,以及在不同系统下哪些是通用的。

    Android SDK 目录下有很多文件夹 xff0c 主要都是干什么的呢 1 add ons 这里面保存着附加库 xff0c 比如google Maps xff0c 当然你如果安装了OPhone SDK xff0c 这里也会有一些类库在里
  • Linux系统文件系统基础罗列

    Linux 文件系统是linux的一个十分基础的知识 xff0c 同时也是学习linux的必备知识 本文将站在一个较高的视图来了解linux的文件系统 xff0c 主要包括了linux磁盘分区和目录 挂载基本原理 文件存储结构 软链接硬链接
  • 至今互联网上收集最全的精品教育资源【转载+补充】

    海慧为您奉上 xff01 xff01 xff01 操作指引 xff1a 第一步 xff1a 注册一个360云盘账号 xff0c 注册地址 xff1a yunpan 360 cn xff0c 拥有自己的账号和密码 第二步 xff1a 下载36
  • Linux Android 真机调试配置

    1 USB 链接手机 xff0c 打开USB调试 2 在终端中输入lsusb命令 xff0c 查看USB设备信息 xff0c 找到手机对应的USB信息 eg Bus 002 Device 003 ID 12d1 1035 Huawei Te
  • 【ROS2】类ROS1的rate定时器写法(c++&python例子)

    在ROS2官方教程里 xff0c 代码和ROS1例程有很大不同 xff0c 大部分节点都使用了类的写法 xff0c 并且用到了很多C 43 43 的新功能 其中 xff0c 发布消息是采用了一个定时器timer xff0c 并且注册一个回调
  • C++中STL常用容器的优点和缺点

    我们常用到的STL 容器 有vector list deque map multimap set和multiset xff0c 它们究竟有何区别 xff0c 各自的优缺点是什么 xff0c 为了更好的扬长避短 xff0c 提高程序性能 xf
  • APM飞控学习之路:5 串口概述与收发调试

    云中谁寄锦书来 xff0c 雁字回时 xff0c 月满西楼 当无人机在空中飞翔时 xff0c 从APM飞控到飞手之间有几条看不见的 风筝线 xff08 1 xff09 2 4GHz的遥控 xff1b xff08 2 xff09 433 91
  • 【Android车载系列】第3章 车载通讯CAN协议

    1 CAN总线的基本概念以及由来 1 1 简介 CAN 总线即控制器局域网总线 CAN xff0c Controller Area Network 是一种用于实时应用的串行通讯协议总线 xff0c 被公认为最有发展前景的现场总线之一 由 B
  • 经典面试题---linux启动流程

    linux启动流程 xff1a power on gt BIOS加电自检 xff0c 根据引导顺序启动 gt MBR gt grub stage2 gt boot grub grub conf gt 加载内核和ramfs文件系统 gt in
  • APM添加超声模块及定高程序分析

    给飞控添加新的模块 xff0c 通常的做法是写驱动文件 xff0c 然后用uORB订阅消息 xff0c 这种方法已经有文章介绍了 xff0c 下面介绍另一种更加简洁的方法 硬件连接 UARTD xff08 ttyS2 xff09 超声 Bo
  • 光流定点若干问题分析

    一 光流摄像头移动速度快慢对结果的影响 实际测试发现 xff0c 在一定高度水平慢速移动光流摄像头20个单位长度 xff0c 光流累加值为6 9 Pixel xff0c 水平快速移动光流摄像头20个单位长度 xff0c 光流累加值为50 6
  • 光流定点程序梳理

    本文主要分析飞控获取到光流数据之后 xff0c 如何实现定点 xff0c 至于光流算法 xff0c 不在本文讨论范围内 官网介绍的PX4 Flow采用STM32F4作为主控 xff0c 定点效果不错 xff0c 但价格稍贵 xff0c 而且
  • 关于SM2加密验签的操作

    对接银行的统一收单系统 xff0c 用到SM2加密验签流程 xff1a 1 xff1a 统一收单系统对接平台商户需要向CFCA申请复合证书 xff0c 一个用于商户签名 xff0c 另外一个用于报文加密 2 xff1a 平台商户入驻成功后
  • Vue脚手架运行报错multi-word-component-names

    问题描述 Vue脚手架运行的报错 error Component name Union should always be multi word vue multi word component names You may use speci
  • ucosIII学习总结

    看到以前写的ucos博客还有人看 xff0c 感到很欣慰 xff0c 写篇博客给刚学习ucos的同学一些建议 xff0c 希望对你们的学习有所帮助 写在前面 xff0c 当初学ucos完全是误打误撞 xff0c 从单片机一路走来 xff0c

随机推荐

  • Ubuntu 18.04 手动配置分区并安装

    环境说明 安装环境 xff1a VMWare WorkStations Pro 15 5 1 操作系统 xff1a ubuntu 18 04 4 desktop amd64 CPU xff1a 4 核 内存 xff1a 8 GB 磁盘 xf
  • Make 命令(持续更新)

    一 背景 Make是最常用的构建工具 xff0c 诞生于1977年 xff0c 主要用于C语言的项目 但是实际上 xff0c 任何只要某个文件有变化 xff0c 就要重新构建 的项目 xff0c 都可以用Make构建 make只是一个根据指
  • linux c++ 服务器端开发面试必看书籍

    摘自别人博客 xff0c 地址 xff1a http blog csdn net qianggezhishen article details 45951095 打算从这开始一本一本开始看 题外话 xff1a 推荐一个 github 上的
  • K8s网络实战分析之service调用

    在上一篇文章K8s网络实战分析之Calico ipip模式中 xff0c 我们通过Pod之间进行ping操作 xff0c 对基于Calico IPIP模式的K8s网络进行了实战学习与分析 单单进行Pod Pod的访问只是K8s的基础功能 x
  • RTK(Real - time kinematic,实时动态)载波相位差分技术

    GPS和RTK区别在于 xff1a 二者bai指代du不同 二者作用不同 二者原理不同 1 二者指代不同 xff1a RTK是载波dao相位差分技术 xff0c 是实时处理两个测量站载波相位观测量的差分方法 xff1b GPS是全球定位系统
  • RTK+GPS提高定位精度原理解析

    RTK 43 GPS提高定位精度原理解析 xff08 一个小白写给另一个小白系列 xff09 GPS定位原理回顾RTK基本概念RTK组成RTK传输差分示意RTK数据链接坐标转换RTK应用后记 我们在上一篇文章导航定位系统的原理解析 xff0
  • GPS、RTK、PPK三种定位技术的原理及应用

    一 GPS技术 1 原理 之前做过集成GPS功能的产品 xff0c 对这种不以定位为主要功能的产品 xff0c 精度是没有要求的 xff0c 例如我只是用它来得到当前社区的位置 xff0c 一般的GPS模块都能满足要求 理论上 xff0c
  • AT命令与ppp协议

    AT 即Attention xff0c AT指令集是从终端设备 Terminal Equipment xff0c TE 或数据终端设备 Data Terminal Equipment xff0c DTE 向终端适配器 Terminal Ad
  • 无人机开发-图传技术

    2016年 xff0c 是中国无人机市场的元年 xff0c 无人机能够一跃进入大众视野 xff0c 并迅速在大众市场火热发展 xff0c 是很多人始料未及的 从刚开始的空中摄录 xff0c 到后来的实时摄录 xff0c 方便的无人机图传功能
  • 无人机飞行原理

    一 无人机的飞行原理 旋翼和轮子一样 xff0c 是一项神奇的发明 四旋翼无人机更是化作了航拍机 xff0c 满足了许多普通人关于天空的想象 旋翼之所以能飞 xff0c 玩过竹蜻蜓的朋友应该都知道 xff1a 当手的搓动给了竹蜻蜓一个旋转的
  • 汽车电子(一)--- 整车CAN网络介绍

    在了解can网络之前 先了解1个问题 什么是智能硬件与ECU 何为智能硬件 就是包含智能控制单元的硬件 比如发动机 发动机上有一块儿专门负责控制发动机进气量 喷油量 排气量的控制单元 这块单元相当于发动机的大脑 他具有信号发送 信号接收 参
  • 三大框架之hibernate入门学习教程增删改查

    好久没更新分享了 xff01 现在发下三大框架的hibernate便于初学者学习 xff01 另外struts2的那些配置文件代码可以找我要 xff0c 里面包括如何自定义拦截器等等 开始hibernate的学习吧 xff01 首先不多说先
  • 程序员工作5年以上,找工作还看学历吗?

    很多程序员都有这样的觉悟 xff1b 找工作学历是敲门砖 xff0c 没有211 985起步的学历 xff0c 想进一家大公司不太可能 举个例子好了 xff1b 如果你是大厂面试官 xff0c 参与面试的有10个刚刚毕业没有工作经验的普通学
  • jquery ajax无刷新请求Struts2验证用户名密码数据库是否存在

    通过ajax请求验证后台数据是否存在 首先导入struts2的核心包 后台Action代码 import com opensymphony xwork2 ActionSupport public class CodeCheckAction
  • 手把手教你们通过jquery ajax调用查询java struts2后端数据+js拼接字符串

    1 首先新建一个web项目 xff0c 创建一个User实体 package com qm entity public class User private String id private String name private Str
  • python检查URL是否能正常访问

    今天 xff0c 项目经理问我一个问题 xff0c 问我这里有2000个URL要检查是否能正常打开 xff0c 其实我是拒绝的 xff0c 我知道因为要写代码了 xff0c 正好学了点python xff0c 一想 xff0c python
  • js自己写脚本自动操作注册插件,基于chrome浏览器

    大家好 xff01 又到了一周的福利时间 xff0c 今天给大家一个福利 xff0c 以后抢票不需要手动刷新页面了 xff0c 直接用你自己写的插件来控制 xff0c 事先声明 xff0c 本人是js菜鸟 xff0c 所以今天带来的例子都是
  • VMware Workstation Proa安装mac镜像

    首先你得有一个VMware 然后下载好mac镜像文件还有for OS X插件补丁 我这里都已经下载好了 xff0c 又需要的可以在评论里留下邮箱地址 xff0c 我分享给你 现在该有的文件都有了 xff0c 那么我们开始 首先VMware镜
  • Spring事务管理的四种方式(以银行转账为例)

    文章转自 https blog csdn net daijin888888 article details 51822257 本文配套示例代码下载地址 xff08 完整可运行 xff0c 含sql文件 xff0c 下载后请修改数据库配置 x
  • redis秒杀系统数据同步(保证不多卖)

    原文链接 http www cnblogs com shihaiming p 6062663 html 东西不多卖 秒杀系统需要保证东西不多卖 xff0c 关键是在多个客户端对库存进行减操作时 xff0c 必须加锁 Redis中的Watch