Redis如何实现分布式锁
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言如果在一个分布式系统中,我们从数据库中读取一个数据,然后修改保存,这种情况很容易遇到并发问题。因为读取和更新保存不是一个原子操作,在并发时就会导致数据的不正确。这种场景其实并不少见,比如电商秒杀活动,库存数量的更新就会遇到。如果是单机应用,直接使用本地锁就可以避免。如果是分布式应用,本地锁派不上用场,这时就需要引入分布式锁来解决。
由此可见分布式锁的目的其实很简单,就是为了保证多台服务器在执行某一段代码时保证只有一台服务器执行。
为了保证分布式锁的可用性,至少要确保锁的实现要同时满足以下几点:
互斥性。在任何时刻,保证只有一个客户端持有锁。
不能出现死锁。如果在一个客户端持有锁的期间,这个客户端崩溃了,也要保证后续的其他客户端可以上锁。
保证上锁和解锁都是同一个客户端。
一般来说,实现分布式锁的方式有以下几种:
使用MySQL,基于唯一索引。
使用ZooKeeper,基于临时有序节点。
使用Redis,基于setnx命令。
本篇文章主要讲解Redis的实现方式。
实现思路
2021-02-22
Redis
经典leetcode算法题分享(字符串)
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言很多人做leetcode题目找不到方向,或者说很难持之以恒,我这里推荐一种方法,从简单难度开始刷,刷完这个标签的简单难度,再换一个标签,这样循序渐进,把做题的量慢慢提高,还有难度逐渐加大。对于初学者,最重要是趁热打铁,而不是东打一枪西放一炮,趁热打铁才能形成做题的思路。
还有一个问题是,一开始做题往往我们没有思路,只会想到暴力解法,效率只有惨淡的5%,遇到这种情况是很正常的,因为还没开始形成解题的思维。我们可以先看看题解,看完思路再自己写,千万不要照抄,要自己想出来才能锻炼编程能力。
所谓talking is cheap, show me code,那么我们就从字符串开始吧!
20. 有效的括号题目:
给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。2.左括号必须以正确的顺序闭合。
解题思路:
这道题可以应用于校验JSON格式的括号是否正确。从题目上可以知道有效的括号是
2021-02-13
算法
玩转布隆过滤器,其实很简单
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
概念布隆过滤器(BloomFilter)是由一个叫“布隆”的小伙子在1970年提出的,它是一个很长的二进制向量,主要用于判断一个元素是否在一个集合中。
原理在介绍原理之前,要先讲一下Hash函数的概念。
我们在Java中的HashMap,HashSet其实也接触过hashcode()这个函数,哈希函数是可以将任意大小的输入数据转换成特定大小的输出数据的函数,转换后的数据称为哈希值。
哈希函数有以下特点:
如果根据同一个哈希函数得到的哈希值不同,那么这两个哈希值的原始输入值肯定不同。
如果根据同一个哈希函数得到的两个哈希值相等,两个哈希值的原始输入值有可能相等,有可能不相等。
布隆过滤器是由一个很长的二进制向量和一系列的哈希函数组成。那么布隆过滤器是怎么判断一个元素是否在一个集合中的呢?
假设布隆过滤器的底层存储结构是一个长度为16的位数组,初始状态时,它的所有位置都设置为0。
当有变量添加到布隆过滤器中,通过K个映射函数将变量映射到位数组的K个点,并把这K个点的值设置为1(假设
2021-01-31
Redis
什么是缓存雪崩,缓存击穿,缓存穿透
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言Redis作为目前使用最广泛的缓存,相信大家都不陌生。但是使用缓存并没有这么简单,还要考虑缓存雪崩,缓存击穿,缓存穿透的问题,什么是缓存雪崩,击穿,穿透呢,出现这些问题又怎么解决呢,接下来学习一下吧。
缓存雪崩什么是缓存雪崩?
当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死。这就是缓存雪崩。
分析:
造成缓存雪崩的关键在于在同一时间大规模的key失效。为什么会出现这个问题呢,有几种可能,第一种可能是Redis宕机,第二种可能是采用了相同的过期时间。搞清楚原因之后,那么有什么解决方案呢?
解决方案:
1、在原有的失效时间上加上一个随机值,比如1-5分钟随机。这样就避免了因为采用相同的过期时间导致的缓存雪崩。
如果真的发生了缓存雪崩,有没有什么兜底的措施?
2、使用熔断机制。当流量到达一定的阈值时,就直接返回“系统拥
深入探索Redis的五种基础数据类型
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言Redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value的NoSQL数据库。
一般来说,我们都是使用关系型数据库MySQL来存储数据,但是面对着流量高峰,会对MySQL造成巨大的压力,导致数据库性能很差,这时就要使用缓存中间件来降低数据库的压力,这是Redis最常见的使用场景。除了作为缓存使用之外,Redis还有很多使用场景,比如分布式锁,计数,队列等等。
所以Redis对于程序员来说可以算得上是必修课。
安装Redis安装Redis很简单,因为网上教程很多,这里就不再详细讲解,推荐看菜鸟教程:https://www.runoob.com/redis/redis-install.html
Redis的特点要用好Redis,首先要明白它的特点:
读写速度快。redis官网测试读写能到10万左右每秒。速度快的原因这里简单说一下,第一是因为数据存储在内存中,我们知道机器访问内存的速度是远远大于访问磁盘的,其次是Redis采用单线程的架构,避免了
2021-01-18
Redis
死磕synchronized关键字底层原理
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言作为Java程序员,我们都知道在多线程的情况下,为了保证线程安全,经常会使用synchronized和Lock锁。Lock锁之前写过一篇《不得不学的AQS》,已经详细讲解过Lock锁的底层原理。这次我们讲一下日常开发中常用的关键字synchronized,想要用得好,底层原理必须要搞明白。
synchronized是JDK自带的一个关键字,在JDK1.5之前是一个重量级锁,所以从性能上考虑大部分人会选择Lock锁,不过毕竟是JDK自带的关键字,所以在JDK1.6后对它进行优化,引入了偏向锁,轻量级锁,自旋锁等概念。
一、synchronized的使用方式在语法上,要使用synchronized关键字,需要把任意一个非null对象作为”锁”对象,也就是需要一个对象监视器(Object Monitor)。总的来说有三种用法:
1.1 作用在实例方法修饰实例方法,相当于对当前实例对象this加锁,this作为对象监视器。
public synchronized void hello()
2021-01-18
并发编程
不得不懂的explain关键字
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi
前言在MySQL中,我们知道加索引能提高查询效率,这基本上算是常识了。但是有时候,我们加了索引还是觉得SQL查询效率低下,我想看看有没有使用到索引,扫描了多少行,表的加载顺序等等,怎么查看呢?其实MySQL自带的SQL分析神器Explain执行计划就能完成以上的事情!
Explain有哪些信息先确认一下试验的MySQL版本,这里使用的是5.7.31版本。
只需要在SQL语句前加上explain关键字就可以查看执行计划,执行计划包括以下信息:id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra,总共12个字段信息。
然后创建三个表:
CREATE TABLE `tb_student` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(36) NOT NULL,
PRIMARY KEY (`id
2021-01-10
MySQL
4千字详细讲解JVM中的垃圾回收
思维导图
前言Java相对于C/C++语言来说,最明显的特点在于Java引入了自动垃圾回收。垃圾回收(Garbage Collection简称GC)可以使程序员不在需要关心JVM内存管理的问题,专注于写程序本身。平时程序员是很难感知到GC的存在,但是如果涉及到一些性能调优,线上的问题排查等等,深入地了解GC是必不可少的。往往通过一些JVM参数的设置能就使系统性能提高不少。
一、JVM内存区域要深入了解GC,首先要明白GC会回收哪些数据,数据位于哪个区域。接着我们看一下JVM的内存区域。
从图中可以看出,内存区域分为五个:
虚拟机栈:线程私有,由一个个栈帧组成,每个栈帧对应着一个调用的方法,保存有方法的局部变量等信息。方法被调用时栈帧入栈,方法结束调用时栈帧出栈。入栈出栈的时机很清楚,所以不需要进行GC。
本地方法栈:与虚拟机栈非常类似,本地方法栈与虚拟机栈的区别在于,虚拟机栈执行的是Java方法,本地方法栈执行的是本地方法(Native Method)。这块区域也不需要进行GC。
程序计数器:线程私有的,它的作用可以看做是当前线程所执行的字节码的行号指示器。我们知道JVM的多线程是
Spring用了哪些设计模式,能讲讲吗
思维导图
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary
概述一个优秀的框架肯定离不开各种设计模式的运用,Spring框架也不例外。因为网上很多文章比较散乱,所以想总结一下在Spring中用到的设计模式,希望大家看完之后能对spring有更深层次的理解。
工厂模式工厂模式我们都知道是把创建对象交给工厂,以此来降低类与类之间的耦合。工厂模式在Spring中的应用非常广泛,这里举的例子是ApplicationContext和BeanFactory,这也是Spring的IOC容器的基础。
首先看BeanFactory,这是最底层的接口。
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
5千字详细讲解JUC中重要的AQS
思维导图
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary
一、什么是AQS谈到并发编程,不得不说AQS(AbstractQueuedSynchronizer),这可谓是Doug Lea老爷子的大作之一。AQS即是抽象队列同步器,是用来构建Lock锁和同步组件的基础框架,很多我们熟知的锁和同步组件都是基于AQS构建,比如ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore。
实际上AQS是一个抽象类,我们不妨先看一下源码:
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
//头结点
private transient volatile Node head;
//尾节点
private transient volat