1.1、作为数据库的缓存,为数据库减压

通常情况下,数据是存储在数据库的,应用程序也是直接操作数据库。在访问量较小的时候几乎没有什么影响。

一旦读写请求量超过1w,数据库压力剧增,此时可以从数据库角度做处理,比如:

做读写分离,一主一从或者一主多从。

如果压力还持续增大,做分库分表,根据业务将数据库拆分为多个,根据需要,将数据库表拆分为多张表,分别放在多个库,又可以支撑一定的请求。再增大呢,我们继续增加分库分表吗?

当访问量超过10w, 100w, 1000w呢,其实这时候我们需要引入缓存,因为大多数的操作都是查询操作。

将访问过的数据存储起来,当再次访问时,先找到缓存,缓存命中就直接返回。找不到再查询数据库,并且回填缓存,下次访问就能直接命中缓存了。

1.2、提高系统响应速度

数据库的数据实际上是存储在文件里的,比如mysql,你可以在它的data目录下面看到,当数据需要迁移时,甚至可以直接拷贝磁盘文件,再稍作修改就可以实现数据迁移。与磁盘打交道,就需要与内存做交换,做swap操作。性能时比较差的。

当大量的并发请求,数据库可能因为太过频繁的IO操作导致无法正常返回结果。而将数据存储在缓存中(redis), 也就是存储在内存中。

而内存天然就支持高并发,可以处理瞬时大量的并发请求。

比如redis的单机qps能后达到11w/s读请求,8w/s写请求。可以说是甩开数据库无数倍。当然我们的响应速度也是得到了一个质的飞跃。

1.3、session共享

我们知道,当我们后台启动多台tomcat之后,上层再加了一层nginx做负载均衡的话,我们就会惊奇的发现,有时能够正常访问,,有时不能后正常访问。就是因为两个tomcat的session是不一样的。当然,可以做session复制等操作解决,但是性能比较低下。并且难以保证各个session之间完全同步。

如何解决呢?当然是使用redis来存储session,让他它们使用同一个session就ok了。这样就实现了session的共享。

登录成功之后,将session存储到redis,获取session时从redis查询。

1.4、存储token令牌,短信验证码等

session共享虽然解决了问题,但是这些都是基于pc端,或者存在session的内置浏览器中。但是比如app等没有session的,那就是基于token实现登录,登录前的验证码发送也都会存储在redis中。

1.5、做分布式锁

通常来说我们Java程序中的锁,是多线程的锁,是在一个JVM当众生效的,管不了其他JVM中的线程。

而多个进程(JVM)在并发时也会产生问题,也要控制时序性,此时就需要使用分布式锁。

1.5.1、使用Redis的setNX实现分布式锁

当然,这种方式存在并发问题,不值得讨论

1.5.2、使用redission实现分布式锁

public class DistributedRedisLock {//从配置类中获取redisson对象 private static Redisson redisson = RedissonManager.getRedisson();private static final String LOCK_PREFIX = "RedisLock_";//加锁 public static boolean acquire(String lockName) {//声明key对象 String key = LOCK_PREFIX + lockName;//获取锁对象RLock mylock = redisson.getLock(key);//加锁,并且设置锁过期时间3秒,防止死锁的产生 uuid+threadId mylock.lock(2, 3, TimeUtil.SECOND);//加锁成功 return true;}//锁的释放 public static void release(String lockName) {//必须是和加锁时的同一个key String key = LOCK_PREFIX + lockName;//获取所对象 RLock mylock = redisson.getLock(key);//释放锁(解锁)mylock.unlock();}
}

1.6、做乐观锁

Mysql中,同步锁和数据库中的行锁、表锁都是悲观锁

Java中 synchronized和可重入锁等都是悲观锁

悲观锁的性能是比较低的,响应性比较差,而高性能、高响应的锁一般都是使用乐观锁

Redis可以实现乐观锁 watch + incr

public static void main(String[] arg) {String redisKey = "lock";ExecutorService executorService = Executors.newFixedThreadPool(20);try {Jedis jedis = new Jedis("127.0.0.1", 6378);// 初始值jedis.set(redisKey, "0");jedis.close();} catch (Exception e) {e.printStackTrace();}for (int i = 0; i < 1000; i++) {executorService.execute(() -> {Jedis jedis1 = new Jedis("127.0.0.1", 6378);try {jedis1.watch(redisKey);String redisValue = jedis1.get(redisKey);int valInteger = Integer.valueOf(redisValue);String userInfo = UUID.randomUUID().toString();// 没有秒完if (valInteger < 20) {Transaction tx = jedis1.multi();tx.incr(redisKey);List list = tx.exec();// 秒成功 失败返回空list而不是空if (list != null && list.size() > 0) {System.out.println("用户:" + userInfo + ",秒杀成功!当前成功人数:" + (valInteger + 1));}// 版本变化,被别人抢了。else {System.out.println("用户:" + userInfo + ",秒杀失败");}}// 秒完了else {System.out.println("已经有20人秒杀成功,秒杀结束");}} catch (Exception e) {e.printStackTrace();} finally {jedis1.close();}});}executorService.shutdown();
}

缓存的6种常见的使用场景相关推荐

  1. 千万不要这样写代码!9种常见的OOM场景演示

    <Java虚拟机规范>里规定除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能,我们本文就来演示一下这些错误的使用场景. 一. Stac ...

  2. java如何解决缓存问题_4种常见的缓存问题及解决方案详解

    前言 使用缓存可以缓解大流量压力,显著提高程序的性能.我们在使用缓存系统时,尤其是大并发情况下,经常会遇到一些"疑难杂症".本文总结了一些使用缓存时常见的问题及解决方案,以后在遇到 ...

  3. es elasticsearch 几种常见查询场景 二次分组 java读取es的查询json文件

    大家好,我是烤鸭: es中几种常见的查询场景,使用java读取es的json文件进行查询. es 中文使用手册. https://www.elastic.co/guide/cn/elasticsear ...

  4. Redis常见的使用场景

    什么是Redis? Redis是一个非常快速的开源非关系.Key-Value数据库,通常称为数据结构服务器:它存储了五种不同类型值的键映射.用作数据库,缓存和消息代理. Redis和其他键值数据库之间 ...

  5. 几种常见的线程池及使用场景

    为什么要使用线程池? 创建线程和销毁线程的花销是比较大的,这些时间有可能比处理业务的时间还要长.这样频繁的创建线程和销毁线程,再加上业务工作线程,消耗系统资源的时间,可能导致系统资源不足.(我们可以把 ...

  6. transpose算子优化的几种常见场景

    很难写一个kernel就能同时在transpose的所有场景都最优,归纳transpose的几种常见场景可以针对性优化.这里只列出了transpose对轴变换的几种情况,没有考虑shape大小.因此在 ...

  7. MySQL索引失效的几种常见场景

    前言 我们在使用MySQL查询数据的时候,总会遇见没有正确使用到索引的情况. 这里我们列举几种常见的,搜索条件使用了索引列却没有走索引的场景. (以下测试均在MySQL8.0.28中完成,且所有数据均 ...

  8. 常见的几种短信应用场景

    时至今日,短信经过了移动互联网的冲击后,聊天.通讯的功能越来越弱,人们可能已很少打开"短信"窗口与亲朋联系,但作为通知.提醒.验证身份等等功能越来越加强,各行各业都开始注重短信的使 ...

  9. JDK四种常见线程池及使用场景、两种提交任务的方法

    转载:JDK 提供的线程池及使用场景 - 编程猎人 (programminghunter.com) 目录 四种常见线程池 1.newFixedThreadPool 2.newSingleThreadE ...

最新文章

  1. SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
  2. picf509c语言程序,樊媛媛c语言程序设计09编译预处理.pptx
  3. python matplotlab.pyplot.pcolormesh() 函数,以及如何自定义画色彩图 (pcolormesh()与pcolor()的区别)
  4. 写博客一周我有哪些收获
  5. 【建议收藏】centos更新yum源为阿里云
  6. 节约内存:Instagram的Redis实践(转)
  7. 刚学unity3d,跟着仿作了flappy bird,记下一些琐碎的心得!
  8. 简单高效地控制高亮度LED
  9. 让Grub 2来拯救你的 bootloader
  10. java 内存 min_Java内存区域
  11. 类和对象编程(三):构造函数析构函数
  12. asp得到地址栏里?以后的字串
  13. ​​​LabVIEW DLL传递一个二维数组报错
  14. 能力值的计算:一年 365 天,以第 1 天的能力值为基数,记为 1.0,当每天好好学习时能力值相比前一天提高 1‰,当没有学习时由于遗忘等原因能力值相比前一天下降 1‰
  15. TCHAR char
  16. 22.11.3打卡 HDU-1069
  17. 软考知识点---12软件工程基础
  18. Python学习日志08 - 字典
  19. GIS工具maptalks开发手册(二)01-02之GeoJSON转化为Geometry——渲染点
  20. 计算机系统实验-DataLab

热门文章

  1. Android绘制饼状图
  2. 双向电源切换开关操作规则,如何选择双向电源自动开关?
  3. IO操作底层调用过程 | 用户态切换内核态原理 | 中断概念
  4. EmEditor如何取消开机自启
  5. 毫无逻辑的UDS随手粘---1
  6. 设计-细说2020最新UI设计趋势与分析
  7. java万年历 视频,万年历.java
  8. perc s100 linux,PERC S100_S300 配置手册
  9. Caffe编译踩坑(一):/usr/include/boost/system/error_code.hpp:233:21: error: looser throw specifier
  10. RabbitMQ pika错误处理 delivery acknowledgement on channel 1 timed out