redis分布式锁

Redlock:Redis分布式锁最牛逼的实现

只谈情不闲聊 提交于 2019-11-27 19:18:02
普通实现 说道Redis分布式锁大部分人都会想到: setnx+lua ,或者知道 set key value px milliseconds nx 。后一种方式的核心实现命令如下: - 获取锁(unique_value可以是UUID等) SET resource_name unique_value NX PX 30000 - 释放锁(lua脚本中,一定要比较value,防止误解锁) if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end 这种实现方式有3大要点(也是面试概率非常高的地方): set命令要用 set key value px milliseconds nx ; value要具有唯一性; 释放锁时要验证value值,不能误解锁; 事实上这类琐最大的缺点就是它加锁时只作用在一个Redis节点上,即使Redis通过sentinel保证高可用,如果这个master节点由于某些原因发生了主从切换,那么就会出现锁丢失的情况: 在Redis的master节点上拿到了锁; 但是这个加锁的key还没有同步到slave节点; master故障,发生故障转移,slave节点升级为master节点; 导致锁丢失。 正因为如此

asp.net core 从单机到集群

故事扮演 提交于 2019-11-27 19:17:44
asp.net core 从单机到集群 Intro # 这篇文章主要以我的活动室预约的项目作为示例,看一下一个 asp.net core 应用从单机应用到分布式应用需要做什么。 示例项目 # 活动室预约提供了两个版本, 集群版 和 单机版 单机版方便部署,不依赖其他环境,数据库使用的是 sqlite,详细部署文档可以参考: https://github.com/WeihanLi/ActivityReservation/blob/dev/docs/deploy/standalone.md 集群版,目前依赖的组件有 mysql(数据库)/redis(缓存)/elasticsearch(日志) 日志 # 日志原来是输出到文件中的,单机部署没有什么问题,可以直接 ssh 到机器上查看文件内容,但是如果部署到集群上,日志再输出到文件的话,排查起来可就有点麻烦了,日志是分散在多台机器上,只看某一台机器上的日志可能并不能解决问题。 基于日志这个痛点让我把日志迁移到 elasticsearch 上,日志统一输出到 es,并通过 kibana 来搜索/分析日志。 日志组件一直用的 log4net,日志输出到 es ,自己写了一个 es 的 Appender, 但是后来越来越觉得 log4net使用起来不够灵活,后来日志组件换成了 serilog,使用 serilog 就可以方便的扩展

Redis来啦~~

独自空忆成欢 提交于 2019-11-27 18:30:31
一. 先聊点别的   1. sql & nosql    sql指关系型数据库,如Oracle,MySQL等,nosql泛指非关系型数据库,如MongoDB,Redis等;SQL数据存在特定结构的表中,而NoSQL则更加灵活和可扩展,存储方式可以是JSON文档,哈希表或其他方式;在sql中必须定义好表和字段结构后才能添加数据,如主键,索引,触发器,存储过程等,表结构虽然可以在定义之后被更新,但是如果有比较大的结构变更的化就会变得比较复杂,在nosql中,数据可以在任何时候任何地方添加,不需要先定义表,nosql也可以在数据集中船舰索引;综上:nosql更加适合初始化数据还不明确或者未定的项目中。   2. ACID & CAP & BASE   ACID是指在数据库管理系统中,事务所具有的四个特性:原子性,一致性,隔离性,持久性;   CAP是指一致性,可用性和分区容错性,CAP理论指这三个要素最多只能实现两个;   BASE接受最终一致性的理论支持,BasicallyAvalable基本可用,Soft-state软状态/柔性事务,EventuallyConsistency最终一致性; 二. Redis:REmote DIctionary Server(远程字典服务器) 1. 什么是Redis?有什么优点?   Redis是存储kv数据结构的分布式数据库;   a. 读写速度快

redis学习

[亡魂溺海] 提交于 2019-11-27 16:51:58
1.什么是redis? Redis的的是完全开源免费的,遵守BSD协议,是一个高性能的键值数据库。是当前最热门的的的NoSql数据库之一,也被人们称为数据结构服务器。 Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库。Redis全称为:Remote Dictionary Server(远程数据服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sorted set)、hash。 2.Redis支持的数据类型? String字符串: 格式: set key value string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。 string类型是Redis最基本的数据类型,一个键最大能存储512MB。 Hash(哈希) 格式: hmset name key1 value1 key2 value2 Redis hash 是一个键值(key=>value)对集合。 Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。 List(列表) Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边

Redlock(redis分布式锁)原理分析

自作多情 提交于 2019-11-27 16:22:00
Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁; 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击); 官网文档地址如下: https://redis.io/topics/distlock 这个锁的算法实现了多redis实例的情况,相对于单redis节点来说,优点在于 防止了 单节点故障造成整个服务停止运行的情况;并且在多节点中锁的设计,及多节点同时崩溃等各种意外情况有自己独特的设计方法; 此博客或者官方文档的相关概念: 1.TTL:Time To Live;只 redis key 的过期时间或有效生存时间 2.clock drift:时钟漂移;指两个电脑间时间流速基本相同的情况下,两个电脑(或两个进程间)时间的差值;如果电脑距离过远会造成时钟漂移值 过大 最低保证分布式锁的有效性及安全性的要求如下: 1.互斥;任何时刻只能有一个client获取锁 2.释放死锁;即使锁定资源的服务崩溃或者分区,仍然能释放锁 3.容错性;只要多数redis节点(一半以上)在使用,client就可以获取和释放锁 网上讲的基于故障转移实现的redis主从无法真正实现Redlock: 因为redis在进行主从复制时是异步完成的,比如在clientA获取锁后,主redis复制数据到从redis过程中崩溃了

redis处理库存问题

谁都会走 提交于 2019-11-27 14:20:11
12月份重构公司社群活动产品,原来自己不是很成熟,按传统的形式处理卖票的信息-现在回首很多地方都会出问题。 先说下背景:业务是卖票!所以自然而然会遇到高并发下的库存问题 搜了很多网上提供以下几种方案: 1.并发数很小,不考虑并发的话采用Redis的原子操作。缺点也很显然,高并发肯定是有问题的!对应方案如下 http://blog.csdn.net/wujiangwei567/article/details/51210600 2.高并发请求采用队列形式,化解为单线程。消费时再使用Redis原子操作加减库存 3.采用Redis的分布式锁 现在采用的第三种方式 来源: CSDN 作者: 天降爆米花 链接: https://blog.csdn.net/dream20nn/article/details/53490147

库存高并发下的不准确和超卖

戏子无情 提交于 2019-11-27 14:19:27
1、 Redis锁实现方式------ 通过redis的原子性方法setnx来实现 redis为单线程单进程模式,采用队列模式将并发访问变成串行访问,使用 setnx命令实现分布式锁。 通过注解@CacheLock(lockedPrefix = "xx"),setnx key = xx,如果返回1,则客户端获得该锁,执行程序。若其它客户端同时访问时,会返回0,表示该锁已经被获得,则不执行程序,可进行重试,直至超过设置的重试时间,锁超时。 当获得锁的程序执行完成后,通过del key = xx释放锁,其它重试的客户端则可以进入。 2、 程序锁有几种实现方式,如何实现 两种 synchronized和lock 类别 synchronized Lock 存在层次 Java的关键字,在jvm层面上 是一个类 锁的释放 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁 在finally中必须释放锁,不然容易造成线程死锁 锁的获取 假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待 分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待 锁状态 无法判断 可以判断 锁类型 可重入 不可中断 非公平 可重入 可判断 可公平(两者皆可) 性能 少量同步 大量同步 3、 先Select 剩余量 from 表

Redis分布式锁原理

痞子三分冷 提交于 2019-11-27 12:24:50
1. Redis分布式锁原理 1.1. Redisson 现在最流行的redis分布式锁就是Redisson了,来看看它的底层原理就了解redis是如何使用分布式锁的了 1.2. 原理分析 分布式锁要解决的是分布式环境下,并行相同代码的加锁功能;了解过redis分布式锁的人肯定知道,一开始redis作为分布式锁用的是setnx,再这基础上设置个定时过期时间,但这种方式有什么问题呢? 实际上看懂上图的人也就明白了那有什么问题,首先是原子性问题,setnx+过期时间这两个操作必须是原子性的,所以这可以用lua脚本解决 再然后是释放锁的时机该如何定? 不管我们定多少过期时间,都不能保证,在这段时间内锁住的代码执行完成了,所以这个时间定多少都不好; 如果不定时间,当执行完成后释放锁,问题就是如果执行到一半机器宕机,那这把锁就永远放不掉了 那Redisson是如何解决上述问题的呢? 它对代码进行了精简的封装,我们的使用非常简单,甚至我们不用主动设置过期时间 它设计了个watch dog看门狗,每隔10秒会检查一下是否还持有锁,若持有锁,就给他更新过期时间30秒;通过这样的设计,可以让他在没有释放锁之前一直持有锁,哪怕宕机了,也能自动释放锁 而不能获得锁的客户端则是不断循环尝试加锁 通过记录锁的客户端id,可以把它设计成可重入锁 1.3. 存在问题

分布式场景常见问题及解决方案

感情迁移 提交于 2019-11-27 08:27:25
分布式场景常见问题及解决方案 前言: 本文主要是根据平常学习过程中遇到的一些分布式场景常见问题,并作出了解析,有不对或者需要补充的地方,希望广大的程序员朋友们及时改进,另外,想要学习,分布式的朋友,我提供一张分布式的学习路线思维导图,望可以给你们一点建议。 下面进入正题 一、分布式锁 分布式锁是在分布式场景下一种常见技术,通常通过基于redis和zookeeper来实现,本文主要介绍redis分布式锁和zookeeper分布式锁的实现方案和对比: (1)基于redis的普通实现 这个方案的加锁主要实现是基于redis的”SET key 随机值 NX PX 过期时间(毫秒)”指令,NX代表只有key不存在时才设置成功,PX代表在过期时间后会自动释放。 这个方案的释放锁是通过lua脚本删除key的方式,判断value一样则删除key。 使用随机值的原因是如果某个获取到锁的客户端阻塞了很长时间,导致了它获取到的锁已经自动释放,此时可能有其他客户端已经获取到了锁,如果直接删除是有问题的,所以要通过随机值加上lua脚本去判断如果value相等时再删除。 这个方案存在一个问题就是,如果采用redis单实例可能会存在单点故障问题,但如果采用普通主从方式,如果主节点挂了key还没来得及同步到从节点,此时从节点被切换到了主节点,由于没有同步到数据别人就会拿到锁。 (2)redis的RedLock算法

Redis分布式锁进化史

感情迁移 提交于 2019-11-27 08:18:08
Redis分布式锁进化史 张佳 2019年08月14日 Redis分布式锁进化史 近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布式实现方式为Redis,Zookeeper,其中基于Redis的分布式锁的使用更加广泛。 但是在工作和网络上看到过各个版本的Redis分布式锁实现,每种实现都有一些不严谨的地方,甚至有可能是错误的实现,包括在代码中,如果不能正确的使用分布式锁,可能造成严重的生产环境故障,本文主要对目前遇到的各种分布式锁以及其缺陷做了一个整理,并对如何选择合适的Redis分布式锁给出建议。 各个版本的Redis分布式锁 V1.0 tryLock(){ SETNX Key 1 EXPIRE Key Seconds } release(){ DELETE Key } 这个版本应该是最简单的版本,也是出现频率很高的一个版本,首先给锁加一个过期时间操作是为了避免应用在服务重启或者异常导致锁无法释放后,不会出现锁一直无法被释放的情况。 这个方案的一个问题在于每次提交一个Redis请求,如果执行完第一条命令后应用异常或者重启,锁将无法过期,一种改善方案就是使用Lua脚本(包含SETNX和EXPIRE两条命令)