击穿:(redis做缓存用,肯定发生了高并发,到达数据库查询)
设置key 的过期时间,过期后没有这个key,找不到了,就穿过了(其中一个key过期导致并发访问数据库)
LRU (LRU,即:最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的页面。)
LFU (LFU,即:最不经常使用淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的页面)
1.key为null
2.setnx
如果key存在,则什么都不做
在 Redis 里,所谓 SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果,不过很多人没有意识到 SETNX 有陷阱!
比如说:某个查询数据库的接口,因为调用量比较大,所以加了缓存,并设定缓存过期后刷新,问题是当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应,如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存。
3.只有获得锁的去访问DB 并发有了:阻止并发到达DB,redis又没有key
鉴于redis是单进程实例,如果所有请求都没找到这个key的话就由第二轮的第一个请求创建一个key作为锁
setnx()->锁
1.get key
2.setnx
3.1 ok表示获取到锁,去DB
3.2 false表示未获取到锁,sleep ->1
问题:如果第一个人挂了?
可以设置锁的过期时间
问题:没挂,但是锁超时了?
用多线程解决
一个线程获取DB
一个线程监控是否取回来,更新锁时间 穿透:(redis做缓存用,从业务接收查询的是你redis根本不存在的数据,到达数据库查询)
解决方案:
用布隆过滤器
1.client客户端包含
2.客户端包含算法,bitmap->redis
3.redis集成布隆
布隆过滤器只能增加不能删除,所以可以用布谷鸟过滤器替代
空key,查的是空就返回
扩展:
布隆过滤器:
它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
tips:看完这个我们可以知道是一个叫布隆的人提出的一个用来检索一个元素是否在一个集合中的算法,效率高,性能好。
布谷鸟过滤器:
布谷鸟过滤器源于布谷鸟Hash算法,布谷鸟Hash表有两张,分别两个Hash函数,当有新的数据插入的时候,它会计算出这个数据在两张表中对应的两个位置,这个数据一定会被存在这两个位置之一(表1或表2)。一旦发现其中一张表的位置被占,就将改位置原来的数据踢出,被踢出的数据就去另一张表找对应的位置。通过不断的踢出数据,最终所有数据都找到了自己的归宿。
但仍会有数据不断的踢出,最终形成循环,总有一个数据一直没办法找到落脚的位置,这代表布谷Hash表走到了极限,需要将Hash算法优化或Hash表扩容。
布谷鸟过滤器只会存储元素的指纹信息(几个bit,类似于布隆过滤器),由于不是存储了数据的全部信息,会有误判的可能。
由于布谷鸟过滤器在踢出数据时,需要再次计算原数据在另一种表的Hash值,因此作者设计Hash算法时将两个Hash函数变成了一个Hash函数,第一张表的备选位置是Hash(x),第二张表的备选位置是Hash(x)⊕hash(fingerprint(x)),即第一张表的位置与存储的指纹的Hash值做异或运算。这样可以直接用指纹的值 异或 原来位置的Hash值来计算出其另一张表的位置。 雪崩:(redis做缓存用,大量的key同时失效,大量数据到达数据库)
随机过期时间
1.时间性无关
2.零点 业务层加判断,零点延时()-->零点(双11折扣,过了零点开始抢购)-->强依赖击穿方案 分布式锁:
分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。
1.setnx
2.过期时间
3.多线程(守护线程) 延长过期
redisson
zookeeper 做分布式锁 API
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency> @Component
public class TestRedis {
@Autowired
RedisTemplate redisTemplate;
@Autowired
@Qualifier("ooxx")
StringRedisTemplate stringRedisTemplate; @Autowired
ObjectMapper objectMapper; public void testRedis(){
// redisTemplate.opsForValue().set("hello", "hello koukay");
//高级api
/* stringRedisTemplate.opsForValue().set("hello02", "hello koukay");
System.out.println(stringRedisTemplate.opsForValue().get("hello02"));*/
//低级api
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.set("hello03".getBytes(), "123".getBytes());
System.out.println(new String(connection.get("hello03".getBytes()))); /* HashOperations<String, Object, Object> hash = stringRedisTemplate.opsForHash();
hash.put("sean", "name", "
koukay
");
hash.put("sean", "age", "18");
System.out.println(hash.entries("sean"));*/ Person p = new Person();
p.setName("jack");
p.setAge(18); /*Jackson2HashMapper jm = new Jackson2HashMapper(objectMapper, false);
redisTemplate.opsForHash().putAll("sean01" , jm.toHash(p));
Map map = redisTemplate.opsForHash().entries("sean01");
Person person = objectMapper.convertValue(map, Person.class);
System.out.println(person);
System.out.println(person.getName()+"<==>"+p.getAge());*/
//序列化hash值字符串
// stringRedisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
Jackson2HashMapper jm = new Jackson2HashMapper(objectMapper, false);
stringRedisTemplate.opsForHash().putAll("sean02" , jm.toHash(p));
Map map = stringRedisTemplate.opsForHash().entries("sean02");
Person person = objectMapper.convertValue(map, Person.class);
System.out.println(person);
System.out.println(person.getName()+"<==>"+p.getAge()); //获得连接
RedisConnection cc = stringRedisTemplate.getConnectionFactory().getConnection();
//订阅消息
cc.subscribe(new MessageListener() {
@Override
public void onMessage(Message message, byte[] bytes) {
byte[] body = message.getBody();
System.out.println(new String(body));
}
}, "ooxx".getBytes());
while (true){
//发送消息
stringRedisTemplate.convertAndSend("ooxx", "hello");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } @Configuration
public class MyTemplate {
@Bean
public StringRedisTemplate ooxx(RedisConnectionFactory fc){
StringRedisTemplate tp = new StringRedisTemplate(fc);
tp.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return tp;
}
} @SpringBootApplication
public class SpringbootStudyApplication { public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(SpringbootStudyApplication.class, args);
TestRedis redis = ctx.getBean(TestRedis.class);
redis.testRedis(); } }

redis击穿,穿透,雪崩,分布式锁,api(jedis,luttuce)的更多相关文章

  1. redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  2. Redis整合Spring实现分布式锁

    spring把专门的数据操作独立封装在spring-data系列中,spring-data-redis是对Redis的封装 <dependencies> <!-- 添加spring- ...

  3. Redis 如何正确实现分布式锁

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  4. 使用Redis SETNX 命令实现分布式锁

    基于setnx和getset http://blog.csdn.net/lihao21/article/details/49104695 使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其 ...

  5. Redis 上实现的分布式锁

    转载Redis 上实现的分布式锁 由于近排很忙,忙各种事情,还有工作上的项目,已经超过一个月没写博客了,确实有点惭愧啊,没能每天或者至少每周坚持写一篇博客.这一个月里面接触到很多新知识,同时也遇到很多 ...

  6. 在 Redis 上实现的分布式锁

    由于近排很忙,忙各种事情,还有工作上的项目,已经超过一个月没写博客了,确实有点惭愧啊,没能每天或者至少每周坚持写一篇博客.这一个月里面接触到很多新知识,同时也遇到很多技术上的难点,在这我将对每一个有用 ...

  7. 使用Redis SETNX 命令实现分布式锁(转载)

    使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...

  8. 【连载】redis库存操作,分布式锁的四种实现方式[一]--基于zookeeper实现分布式锁

    一.背景 在电商系统中,库存的概念一定是有的,例如配一些商品的库存,做商品秒杀活动等,而由于库存操作频繁且要求原子性操作,所以绝大多数电商系统都用Redis来实现库存的加减,最近公司项目做架构升级,以 ...

  9. 基于 Redis 实现简单的分布式锁

    摘要 分布式锁在很多应用场景下是非常有效的手段,比如当运行在多个机器上的不同进程需要访问同一个竞争资源的时候,那么就会涉及到进程对资源的加锁和释放,这样才能保证数据的安全访问.分布式锁实现的方案有很多 ...

随机推荐

  1. Android实现秒开效果

    0x01 创建SplashActivity 新建一个Activity,取名为SplashActivity 0x02 新建资源 在res/drawable下新建一个splash.xml文件和名为ig_s ...

  2. Blazor 国际化多语言界面 (I18nText )

    在实际使用中,我们经常会遇到需要把程序界面多种语言切换,适应不同地区使用者的需求,本文介绍一个我初学Blazor接触到的库,边撸边讲解. 包名: Toolbelt.Blazor.I18nText ht ...

  3. Windows和ubuntu下更改pip国内镜像

    windows下更改pip国内镜像 # 在C:\Users\admin路径下创建pip文件夹,然后创建pip.ini文件, 并在文件下写入 [global] index-url = http://py ...

  4. SpringBoot-总结

    SpringBoot一站式开发 官网:https://spring.io/projects/spring-boot Spring Boot可以轻松创建独立的.基于Spring的生产级应用程序,它可以让 ...

  5. vim 下几种比较省劲的方式(vi结合着用)

    Vim的几种模式 正常模式:可以使用快捷键命令,或按:输入命令行. 插入模式:可以输入文本,在正常模式下,按i.a.o等都可以进入插入模式. 可视模式:正常模式下按v可以进入可视模式, 在可视模式下, ...

  6. docker基础_docker引擎内部原理

    docker引擎内部原理 docker主要由以下主要组件构成:docker客户端.docker守护进程(daemon).containerd.runc.shim daemon daemon的主要功能包 ...

  7. JDK内置锁深入探究

    一.序言 本文讲述仅针对 JVM 层次的内置锁,不涉及分布式锁. 锁有多种分类形式,比如公平锁与非公平锁.可重入锁与非重入锁.独享锁与共享锁.乐观锁与悲观锁.互斥锁与读写锁.自旋锁.分段锁和偏向锁/轻 ...

  8. 数据库基础知识详解五:MySQL中的索引和其两种引擎、主从复制以及关系型/非关系型数据库

    1.MySQL中的索引 在MySQL,索引是由B+树实现的,B+是一种与B树十分类似的数据结构. 形如下面这种: 其结构特点: (1)有n课子树的结点中含有n个关键码. (2)非根节点子节点数: ce ...

  9. 浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配

    Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含自定义扫描组件.自定义导入组件.手动注册组件.自动注入方法和参数.使用Spring容器底层组件等 配置 @Confi ...

  10. mysql内连接查询之自连接

    连接查询: 当查询数据时,通过连接操作查询出存放在多个表中的不同数据,当两个或者多个表中存在相同意义的字段时, 便可以通过这些字段对不同的表进行连接查询. 自连接: 如果在一个连接查询中,涉及的两个表 ...