IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis全面剖析【亿级流量核心技术之一】 -> 正文阅读

[大数据]Redis全面剖析【亿级流量核心技术之一】


一、Redis是什么?

redis是一种基于k-v键值对、存储在内存的 非关系型数据库。

二、Redis的优点

1.读取快速,QPS最高能达到10万(每秒处理10万个请求),纳秒级,是MySQL数据库的100倍;
2.线程安全
3.可持久化
4.应用场景丰富
5.性能强大,受限于内存,不是redis不够强,而是被服务器内存限制了

三、Redis 的 5 种数据类型

 1.String      字符串(包含int)
 2.List        可重复集合
 3.set         不可重复集合
 4.zest        不可重复、有序集合
 5.hash        哈希散列表

四、Redis的主要应用场景

?网上一大推花里胡哨的应用场景,眼睛都看花了,什么消息队列、订阅与发布等等,个人觉得没必要去学,确实能实现,但这些场景没有更好的组件和工具吗?不要为了技术而技术,做开发永远要追求性能,Redis设计之初就是用来做缓存的,在缓存方面Redis才是性能之王,这里只介绍最常用的6个,基于缓存的应用场景:

1.临时数据

对临时数据、不重要的数据进行存储,无需存储数据库,用完即删。

2.热点数据

一些经常被访问、被大量客户端访问的热点数据,比如微博大瓜、秒杀商品、排行榜等等,放到缓存中,降低Mysql数据库的压力。

3.分布式锁

对于分布式应用想要给线程加锁,但又由于多服务器的特征,就需要一个线程安全的中间件存储这个锁,redis完美的符合这个要求。

4.全局主键ID

对于分库分表的场景,数据库部署在多台服务器上,单靠数据库自身的“主键不允许重复”特性无法避免主键重复,就需要一个中间件来统一管理全局主键ID。

5.计数器

频繁访问、修改,但又不是很重要的数据,允许延迟展示,文章阅读量、点赞数等,先放到缓存中,再通过定时任务同步到数据库中。

6.限流

防止恶意用户暴力破解、攻击服务器。
· 以访问者的IP或其它信息作为key,单位时间内访问次数超过N次就直接返回false,比如1秒内访问超过10次就不允许再访问。
· 限制密码错误登录次数,比如密码错误登录失败3次弹出验证码校验、失败5次就锁定账户不允许再登录。

五、Redis在Java中的简单应用(以jedis为例)

1.pom依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.2.0</version>
</dependency>

2.application.properties配置

# Redis 数据库索引(默认为 0)
spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
# Redis 服务器连接密码(默认为空)
spring.redis.password=
# springboot 2.0 redis默认客户端已换成lettuce
 
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
# 连接超时
spring.redis.timeout=5000

3.创建jedis对象

1)本地

		//连接本地的 Redis 服务
        Jedis jedis = new Jedis("localhost");

2)指定IP

		//连接指定ip的 Redis 服务,6379是redis的端口号
        Jedis jedis = new Jedis("IP地址",6379);

4.常用API

1)set

// 在redis中存入String
jedis.set("key", "String");

2)get

// 从redis中获取key对应的value
String value = jedis.get("key");

3)lpush

// 往redis中存入list
jedis.lpush("list","Google");
jedis.lpush("list","360");
jedis.lpush("list","Edge");

4)lrange

// 获取存储的List并输出
List<String> list = jedis.lrange("site-list", 0 ,2);
for(int i=0; i<list.size(); i++) {
   System.out.println("列表项为: "+list.get(i));
}

5)keys

// 获取redis中存入的所有键
Set<String> keys = jedis.keys("*"); 

6)setnx

// 如果存在则不操作,不存在则存入
jedis.setnx(String key,String value); 

7)del

// 删除键为key的数据
jedis.del(String key); 

8)exists

// 判断键是否存在
jedis.exists(String key); 

9)expire

// 设置键key的过期时间 单位:秒
jedis.expire(String key,int seconds); 

10)incr

// key的值 自增1
jedis.incr(String key); 

11)decr

// key的值 自减1
jedis.decr(String key); 

六、Redis的三大坑

在做缓存的时候,除了提前放上去的数据,一般都是缓存中不命中才被动写的,并且出于容错考虑,在缓存中取不到的时候再去数据库中取,这就遗留了一个重大风险,缓存失效时数据库瞬时压力过大导致宕机!

1.缓存穿透

在这里插入图片描述

缓存中没有、数据库中也没有的数据,而用户却不停的访问,比如访问商品ID为 -1(不存在的数据)、恶意用户暴力攻击。
解决方案:
1.限流;
2.token校验;
3.缓存中取不到时,去数据库取,数据库中也没有,就在缓存中设置为 key-null,下次再访问,就在缓存中取到null值,不会再去查数据库。

2.缓存击穿

在这里插入图片描述

缓存中没有,而数据库中有,一般是缓存过期,导致大量访问落到数据库上,瞬时压力过大。
解决方案:
1.设置热点数据永不过期(除非服务器挂了
2.熔断,设置服务降级、熔断,快速返回机制。
3.加锁:当缓存中获取不到,要去数据库中查询之前,先去抢锁,第一个抢到锁的线程才有资格去查询数据库,查到之后把数据放到缓存中,后面的线程就能从缓存中取到数据。
4.布隆过滤器:redis 4.X版本以后,官方自带的一个插件。用于快速判断一个值是否存在于某个容器中,当请求的key不存在布隆过滤器中,就没必要进行后面的操作,直接返回null。

  • bf.add:添加元素到布隆过滤器中;
  • bf.exists:判断某个元素是否在过滤器中

3.缓存雪崩

在这里插入图片描述
缓存中的数据大批量、同时过期,使得大量查询落到数据库上,瞬时压力过大造成宕机。
解决方案:
1.热点数据设置永不过期;
2.过期时间散列分布,避免集中过期;
3.如果部署了多个redis服务,缓存数据均匀分布。

简单记忆:
1.发送的请求穿过了缓存,也穿过了数据库,缓存穿透。
2.发送的请求穿过了缓存,落到了数据库,缓存击穿。
3.同时出现大量击穿,像雪崩一样冲过来,缓存雪崩。

七、Redis实现分布式锁

业务流程:

在这里插入图片描述

获取锁的方式(基于Jedis):

1.set(String key, String value, String nxxx, String expx, int time)

以NX方式设置key,同时设置过期时间。设置成功返回 OK
推荐方式,一条命令处理,具有原子性,设置过期时间避免死锁。

/**
* key    键
* value  值
* "NX"   表示以NX方式设置
* “EX”   表示设置过期时间,单位秒;PX :单位毫秒;
* expireSeconds   过期时间
*/
jedis.set(key, value, "NX", "EX", expireSeconds)
private static boolean getLock(String key, String value) {
        String result = jedis.set(key, value, "NX", "EX", 30);
        if ("OK".equals(result)) {
            return true;
        }
        return false;
    }

2.setnx + value(expiretime)

以NX方式设置key,并把时间当作value存入,获取时判断时间是否过期。
过于麻烦,没有第一种方便。

3.setnx + expire

以NX方式设置key,成功后再设置过期时间。
分步执行,不是原子性,存在风险。

八、Redis是单线程吗?

很明确的说,是。正是因为单线程、线程安全的特性,才能用来做分布式锁,用来管理秒杀商品的数量。
6.x版本以后加入了IO多线程,也就是内存对于磁盘的“读/写”操作变成了多线程,可以同时“读/写”多条数据,但只有一个工作线程,处理数据的线程是串行的。redis本身是线程安全的,程序需要自己保证外部的线程安全。

6.x版本以前,读写串行、处理串行

在这里插入图片描述

6.x版本以后,读写并行、处理串行

1.提高程序执行效率;
2.提高系统及硬件资源的利用率;
在这里插入图片描述

九、Redis持久化

Redis的数据是存储在内存中的,一旦服务器关闭、宕机、重启,数据就会丢失,故某些情况就需要将数据存入磁盘,这个存入磁盘的过程称为“Redis持久化”,有两种方式:RDB、AOF。

1.RDB(Redis DataBase)

  • 默认开启。
  • 定期对数据遍历,并生成磁盘快照 rdb文件存入磁盘。Redis重启时,通过RDB文件恢复数据。
  • 每次遍历时都会消耗内存,如果数据量大,会造成磁盘IO阻塞。rdb操作完成,才会执行redis其它操作。
  • 日志形式,保存每条set记录,磁盘上生成aof文件,Redis重启时,运行这些set命令达到恢复数据的目的。

2.AOF(Append Only File)

  • 保存每一条新增命令,恢复数据时就是重新执行这些命令。
  • 是一个持续追加文件,当文件达到上一次重写的2倍,且超过64M时,会重新遍历所有数据,重写aof文件。数据量过大时,也会对内存造成压力。

3.使用建议

  • 只是用来做缓存的话,建议两种方式都不要开启
  • 主机上关闭持久化,在从机上做持久化
  • 有数据持久化需求时,两种都开启,可最大程度的保证数据完整性
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 21:14:25  更:2022-02-14 21:16:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:26:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码