分布式锁

volatile关键字的作用

巧了我就是萌 提交于 2020-01-20 17:45:29
引言   昨日接了一个阿里外包的电话面试,问了一些技术问题感觉到自己是真的菜,接触Java开发已经也有一段时间,技术方面说来惭愧,一直以来只是局限于框架工具的用法,也没有进行了解其实现的原理,更重要的是一直没有归纳和总结,这次把这些问题记录下来,相关的知识点也找了一些资料学习下。 问题 1. CountDownLanch的工作原理 实现原理:计数器的值由构造函数传入,并用它初始化AQS的state值。当线程调用await方法时会检查state的值是否为0,如果是就直接返回(即不会阻塞);如果不是,将表示该节点的线程入列,然后将自身阻塞。当其它线程调用countDown方法会将计数器减1,然后判断计数器的值是否为0,当它为0时,会唤醒队列中的第一个节点,由于CountDownLatch使用了AQS的共享模式,所以第一个节点被唤醒后又会唤醒第二个节点,以此类推,使得所有因await方法阻塞的线程都能被唤醒而继续执行。   引用别人的博客里的一段话,详细请点击: Java并发包中CountDownLatch的工作原理、使用示例 题外话: 什么是 AQS(抽象的队列同步器) AbstractQueuedSynchronizer类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问 共享资源的同步器框架,许多同步类实现都依赖于它,如常用的 ReentrantLock/Semaphore

Redis 分布式锁的实现

删除回忆录丶 提交于 2020-01-20 16:20:25
分布式锁的原理: 分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。。在分布式系统中,常常需要协调他们的动作。 如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。 setnx 是『SET if Not eXists』(如果不存在,则 SET)的简写。 命令格式:SETNX key value;使用:只在键 key 不存在的情况下,将键 key 的值设置为 value 。若键 key 已经存在, 则 SETNX 命令不做任何动作。返回值:命令在设置成功时返回 1 ,设置失败时返回 0 。 getset 命令格式:GETSET key value,将键 key 的值设为 value ,并返回键 key 在被设置之前的旧的value。返回值:如果键 key 没有旧值, 也即是说, 键 key 在被设置之前并不存在, 那么命令返回 nil 。当键 key 存在但不是字符串类型时,命令返回一个错误。 expire 命令格式:EXPIRE key seconds,使用:为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。返回值:设置成功返回 1 。 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的

redis和memcache的区别分析

陌路散爱 提交于 2020-01-20 11:49:20
传统MySQL+ Memcached架构遇到的问题   实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:    1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。   2.Memcached与MySQL数据库数据一致性问题。   3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。   4.跨机房cache同步问题。  众多NoSQL百花齐放,如何选择   最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题    1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。   2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。   3

基于Lua脚本实现Redis分布式锁(乐观锁)

大兔子大兔子 提交于 2020-01-20 10:29:25
使用redis调用lua脚本实现原子性操作 如果对redis提供的指令集不满足 可以通过lua脚本执行自定义操作来保证执行的原子性,比如实现将匹配 key 和删除 key 合并在一起执行等。 Redis 服务器会单线程原子性执行 lua 脚本,保证 lua 脚本在处理的过程中不会被任意其它请求打断。 public class RedisLock { private JedisTemplate jedisTemplate = SpringContextHolder.getBean(JedisTemplate.class); private static final Logger logger = LoggerFactory.getLogger(RedisLock.class); private final static String REDIS_PREFIX = "redis_prefix_"; private final static String NX = "NX"; private final static String PX = "PX"; private final static String OK = "OK"; /** * 超时时间 * 默认1秒 */ private Integer timeout = 1_000; private String lockName; /

Redis面试题总结

不羁岁月 提交于 2020-01-19 15:12:42
如何用Redis做异步队列 一般使用list结构作为队列,rpush生产消息,lpop消费消息,当lpop没有消息的时候,需要适当sleep一会再重试 或者不用sleep使用blpop在没有消息的时候,它会阻塞住直到消息的到来 可以使用pub/sub主题订阅者模式,可以实现1:N的消息队列 pub/sub缺点:在消费者下线的情况下,生产的消息会丢失,要使用专业的消息队列(RocketMQ) Redis如何实现延时队列 使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理 机器突然掉电会怎么样 取决于AOF日志sync属性的配置,如果不要求性能,在每条指令时都sync一下磁盘,就不会丢失数据。但在高性能的要求下一般都是使用定时sync。 Pipeline有什么好处,为什么要使用Pipeline 可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。 多个操作系统同时操作Redis带来的数据问题 可以基于Zookeeper实现分布式锁,每个系统通过Zookeeper获取分布式锁,确保同一时间

剑指Offer(Redis)——实现分布式锁

孤街浪徒 提交于 2020-01-19 01:39:11
分布式锁是控制分布式系统或者不同系统之间共同访问共享资源的一种锁的实现,当不同主机共享了共享某一种资源时候往往通过互斥来除去彼此的干扰来保证一致性。 什么是分布式锁?分布式锁需要解决什么问题? 互斥性 任意时刻只能有一个客户端获得锁 安全性 锁只能被持有该锁的客户端删除,不能被其他客户端删除 死锁 获得锁的客户端,出现意外宕机锁无法释放,资源也被永远锁住就出现了死锁 容错性 客户端出现宕机,可以是实现高可用 Redis实现分布式锁 1、首先使用get < key >检查被上分布式锁的key,返回nil表示没有上锁,返回string是锁的名字 2、使用setnx < key > < lockname >设置锁住的key和锁的名字,被锁住返回0反之返回1 设置锁之后,给锁设置一个过期时间也是必须的,也不能一直锁着手动去释放,所以我们就需要设置所的过期时间: 给上面的锁设置失效时间,失效时间为2s,2s后检查锁的状态 设置锁之后发现锁的状态有了明显的转变,实现的伪代码如下: 但是存在一个问题,使用setnx设置锁之后,设置失效时间之前就失效了那么就会一直处于被锁的状态,其他线程无法获得锁,简单来说就是 无法保证原子性。 Redis存在一种新的方法,将setnx和expire的功能结合在一起,开发出有过期时间的锁: SET key value [ EX seconds ] [ PX

Redis的两个典型应用场景

最后都变了- 提交于 2020-01-18 22:21:31
Redis简介 Redis 是目前业界使用最广泛的内存数据存储。相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化。除此之外,Redis还提供一些类数据库的特性,比如事务,HA,主从库。可以说Redis兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。本文介绍Redis在Spring Boot中两个典型的应用场景。 场景1:数据缓存 第一个应用场景是数据缓存,最典型的当属缓存数据库查询结果。对于高频读低频写的数据,使用缓存可以第一,加速读取过程,第二,降低数据库压力。通过引入spring-boot-starter-redis依赖和注册RedisCacheManager,Redis可以无缝的集成进Spring的缓存系统,自动绑定@Cacheable, @CacheEvict等缓存注解。 引入依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> Redis配置(application.properties): 1 # REDIS (RedisProperties) 2 spring.redis.host

Redis实现分布式锁

守給你的承諾、 提交于 2020-01-18 19:31:16
实现原理 基于Redis是单线程, 串行执行的 目的 解决在分布式应用中, 将并发变为串行, 减少数据库压力, 提升安全性能, 真实项目中, 我们是在多个服务器中同时上线我们的代码并被nginx反向代理, 对于并发下单的情况下, 大量的请求同时到达我们的mysql数据库, 我们虽然可以更改事务的隔离级别, 更改为串行执行, 但是多个并发请求压力还是已经到达了mysql中, 有没有什么办法可以在到达mysql之前, 让操作变为串行执行, redis实现分布式锁 模拟并发请求, 不用分布式锁的情况 分布式锁 改进(异常捕获) 改进(增加过期时间) 改进(另开线程实现自选锁) 最终版本 来源: CSDN 作者: 忘记以前 链接: https://blog.csdn.net/itpedestrian/article/details/102977115

Redis 总结

こ雲淡風輕ζ 提交于 2020-01-18 17:19:47
redis 简介 简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。 为什么要用 redis/为什么要用缓存 主要从“高性能”和“高并发”这两点来看待这个问题。 高性能: 假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可! 高并发: 直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。 为什么要用 redis 而不用 map/guava 做缓存? 下面的内容来自 segmentfault 一位网友的提问,地址: https://segmentfault.com/q/1010000009106416 缓存分为本地缓存和分布式缓存。以 Java 为例,使用自带的 map 或者

Redis 基础知识

你离开我真会死。 提交于 2020-01-18 17:19:26
1. 简介:   Redis是Remote Dictionary Server的简写,它是一种key-value形式的NoSql内存数据库,单线程架构,数据存放内存,故读写速度性能非常好;当然也支持内存中数据以快照和日志形式持久化到硬盘,从而在发生异常情况下数据也不会丢失。   特点:A. 性能高,速度快:读写性能能达到10w/s;      B. 丰富的数据结构:如字符串、哈希、列表、集合、有序集合等;      C. 丰富的特性:键过期实现定时缓存、发布订阅实现消息队列、事务功能、管道实现批量处理命令等;      D. 丰富的客户端:主流的开发语言都接入了redis   应有场景:A. 缓存:能够提升网站访问速度,大大降低数据库的压力;        B. 排行榜:有序集合机构实现复杂排行;        C. 计数器:用incr命令实现,适用于商品浏览量及视频播放量等;        D. 分布式会话:集群模式下,用redis搭建session服务;        E. 分布式锁:用setnx实现,适合并发访问高(全局ID、秒杀)的情况,并发不高可用数据库悲观锁和乐观锁控制;        F. 社交网络:用哈希或集合等数据结构实现,适合点赞等;        G. 最新列表:lpush + ltrim来实现        H. 消息系统:适合简单的消息队列, 注意: