Redis基础知识概述

这篇具有很好参考价值的文章主要介绍了Redis基础知识概述。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Redis基础知识概述


一、Redis简介

1、Redis(Remote Dictionary Server 远程字段服务)是一个开源的使用ANSI C语言编写、支持网络、科技与内存亦可持久化的日志型、key-value数据库,并提供多种语言的API。

2、Redis是一个key-value存储系统,它支持存储的value类型相对更多,包括string、list、set、zset(sorted set --有序集合)和hash。这些数据结构都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中,Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

3、Redis提供了java、C/C++、PHP、JavaScript、Perl、Object-C、Python、Ruby、Erlang等客户端,使用很方便。

4、Reids支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他服务器的主服务器。这使得Redis可执行单层数复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

5、 在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tLb9zQWV-1682565151611)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20230421095843441.png)]

二、NoSQL技术

为了克服上述问题,java web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。

Redis和MongoDB是当前使用最广泛的NoSQL, 而就Redis技术而言,它的性能十分优越,可以支持每秒十几万的读写操作,其性能远超数据库,并且还支持集群、。分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。

三、Redis的高并发和快速原因

1.Redis是基于内存的,内存的读写速度非常快;
2.Redis是单线程的,省去了很多上下文切换线程的时间;
3.Redis使用多路复用技术,可以处理并发的连接。非IO内部实现采用epoll,采用了epoll自己实现的简单的事件框架。epoll的读写、关闭、连接都转化为事件,然后利用epoll的多路复用特性,绝不在IO上浪费一点时间。

四、Redis为什么是单线程的

1、官方解释

Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络宽带。既然单线程容易实现,而且CPU不会成为瓶颈,那么顺理成章的采用单线程的方案。

2、详细原因
(1)不需要各种锁的性能消耗

Redis的数据结构并不全是key-value形式的,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash中添加或删除一个对象,这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加。

总之,在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现的死锁而导致的性能消耗。

(2)单线程多进程集群方案

单线程的威力实际上非常强大,每核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的。

所以单线程、多进程的集群不失为一个时髦的解决方案。

(3)CPU消耗

采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU。

但是如果CPU称为Redis的瓶颈,或者不想让服务器其它CPU核闲置,那怎么办?

可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系型数据库,数据之间没有约束。只要客户端分清哪些key放在哪个Redis进程中就可以了。

五、单线程的优劣势

1、优势

  1. 代码更清晰,处理逻辑更简单
  2. 不用考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现死锁而导致的性能消耗
  3. 不存在多线程切换而消耗CPU

2、劣势

无法发挥多核CPU性能优势,不过可以通过单击开多个Redis实例来完善。

六、Redis高并发总结

1、Redis是纯内存数据库,一般都是简单存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快;

2、Redis使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成事件,减少了线程切换时上下文切换和竞争。

3、Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。

4、Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如跳表,使用有序的数据结构加快读写的速度。

5、Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。

七、在java中使用Redis

1、添加Jedis依赖

想要在 Java 中使用 Redis 缓存,需要添加相关的Jar包依赖,打开Maven仓库的网站:https://mvnrepository.com/ ,搜索Jedis:

Redis基础知识概述

把它导入工程中去就可以啦,下面我们来对Redis的写入性能做一下测试:

@Test
public void redisTester() {
    Jedis jedis = new Jedis("localhost", 6379, 100000);
    int i = 0;
    try {
        long start = System.currentTimeMillis();// 开始毫秒数
        while (true) {
            long end = System.currentTimeMillis();
            if (end - start >= 1000) {// 当大于等于1000毫秒(相当于1秒)时,结束操作
                break;
            }
            i++;
            jedis.set("test" + i, i + "");
        }
    } finally {// 关闭连接
        jedis.close();
    }
    // 打印1秒内对Redis的操作次数
    System.out.println("redis每秒操作:" + i + "次");
}
-----------测试结果-----------
redis每秒操作:10734

2、使用Redis连接池

跟数据库连接池相同,Java Redis也同样提供了类 redis.clients.jedis.JedisPool来管理我们的Reids连接池对象,并且我们可以使用 redis.clients.jedis.JedisPoolConfig来对连接池进行配置,代码如下:

JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大空闲数
poolConfig.setMaxIdle(50);

// 最大连接数
poolConfig.setMaxTotal(100);

// 最大等待毫秒数
poolConfig.setMaxWaitMillis(20000);

// 使用配置创建连接池
JedisPool pool = new JedisPool(poolConfig, "localhost");

// 从连接池中获取单个连接
Jedis jedis = pool.getResource();

// 如果需要密码
//jedis.auth("password");

Redis只能支持六种数据结构 (string/hash/list/set/zset/hyperloglog)的操作 ,但在Java中我们通常以类对象为主,所以在Redis存储的数据结构月java对象之间进行转换,如自己编写一些工具类 比如一个角色对象的转换,还是比较容易的,但是涉及到许多对象的时候,这其中无论工作量还是工作难度都是很大的,所以总体来说, 就操作对象而言,使用Redis还是挺难的,好在spring对这些进行了封装和支持。

八、Redis在Java Web中的应用

Redis 在 Java Web 主要有两个应用场景:

  • 存储缓存用的数据
  • 需要高速读写的场合

1、存储缓存用的数据

在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。

如果放在Redis中,也就是放在内存中,让服务器直接读取内存中的数据,那么速度就会快很多,并且会极大减少数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用Redis存储一些常用的和主要的数据,比如用户登录信息等。

一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:

(1)业务数据常用吗?使用率如何?

如果使用率较低,就没必要写入缓存。

(2)该业务是读操作多,还是写操作多?

如果写操作多,频繁需要写入数据库,也没必要使用缓存。

(3)业务数据大小如何?

如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没必要。

在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!使用 Redis 作为缓存的读取逻辑如下图所示:

Redis基础知识概述

从上图我们可以知道以下两点:

(1)当第一次读取数据的时候,读取Redis的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入Redis中

(2)当第二次以及以后需要读取数据时,就会直接读取Redis,读取数据后就结束了流程,这样速度大大提高了。

从上面的分析可以知道,读操作的可能性是远大于写操作的,所以使用 Redis 来处理日常中需要经常读取的数据,速度提升是显而易见的,同时也降低了对数据库的依赖,使得数据库的压力大大减少。

分析了读操作的逻辑,下面我们来看看写操作流程:

Redis基础知识概述

从流程可以看出,更新或者写入的操作,需要多个 Redis 的操作,如果业务数据写次数远大于读次数那么就没有必要使用 Redis。

2、高速读写场合

在如今的互联网中,越来越多的存在高并发的情况,比如天猫双11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流水,重则数据库瘫痪,服务宕机,而这样的场合都是不允许的!

所以我们需要使用 Redis 来应对这样的高并发需求的场合,我们先来看看一次请求操作的流程:

Redis基础知识概述

我们来进一步阐述这个过程:

(1)当一个请求到达服务器时,只是把业务数据在Redis上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速相应的需求。

(2)但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完Redis的读写之后,会去判断该高速读写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将Redis的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

九、在spring中使用Redis

上面说到了 Redis 无法操作对象的问题,无法在那些基础类型和 Java 对象之间方便的转换,但是在 Spring 中,这些问题都可以通过使用RedisTemplate得到解决!

想要达到这样的效果,除了 Jedis 包以外还需要在 Spring 引入 spring-data-redis 包。

1、使用spring配置JedisPoolConfig对象

大部分的情况下,我们还是会用到连接池的,于是先用 Spring 配置一个 JedisPoolConfig 对象:

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    
    <!--最大空闲数-->
    <property name="maxIdle" value="50"/>

    <!--最大连接数-->
    <property name="maxTotal" value="100"/>

    <!--最大等待时间-->
    <property name="maxWaitMillis" value="20000"/>

</bean>

2、为连接池配置工厂模型

好了,我们现在配置好了连接池的相关属性,那么具体使用哪种工厂实现呢?在Spring Data Redis中有四种可供我们选择的工厂模型,它们分别是:

  • JredisConnectionFactory
  • JedisConnectionFactory
  • LettuceConnectionFactory
  • SrpConnectionFactory

我们这里就简单配置成JedisConnectionFactory:

<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">

    <!--Redis服务地址-->
    <property name="hostName" value="localhost"/>

    <!--端口号-->
    <property name="port" value="6379"/>

    <!--如果有密码则需要配置密码-->
    <!--<property name="password" value="password"/>-->

    <!--连接池配置-->
    <property name="poolConfig" ref="poolConfig"/>

</bean>

3、配置RedisTemplate

普通的连接根本没有办法直接将对象直接存入 Redis 内存中,我们需要替代的方案:将对象序列化(可以简单的理解为继承Serializable接口)。我们可以把对象序列化之后存入Redis缓存中,然后在取出的时候又通过转换器,将序列化之后的对象反序列化回对象,这样就完成了我们的要求:

Redis基础知识概述

RedisTemplate可以帮助我们完成这份工作,它会找到对应的序列化器去转换Redis的键值:

<bean id="redisTemplate"
      class="org.springframework.data.redis.core.RedisTemplate"
      p:connection-factory-ref="connectionFactory"/>

4、测试

首先编写好支持我们测试的POJO类:

/**
 * @author: 素小暖
 * @create: 2020-2-12
 */

public class Student implements Serializable{
    private String name;
    private int age;

    /**    
     * 给该类一个服务类用于测试
     */
    
    public void service() {
        System.out.println("学生名字为:" + name);
        System.out.println("学生年龄为:" + age);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

然后编写测试类:

@Test
public void test() {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    RedisTemplate redisTemplate = context.getBean(RedisTemplate.class);
    Student student = new Student();
    student.setName("我没有三颗心脏");
    student.setAge(21);
    redisTemplate.opsForValue().set("student_1", student);
    Student student1 = (Student) redisTemplate.opsForValue().get("student_1");
    student1.service();
}

十、springboot中使用Redis

1、在springboot中添加Redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、添加配置文件application.peoperties

# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0

# Redis服务器地址
spring.redis.host=localhost

# Redis服务器连接端口
spring.redis.port=6379

# Redis服务器连接密码(默认为空)
spring.redis.password=

# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8

# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1

# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8

# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0

# 连接超时时间(毫秒)
spring.redis.timeout=0

3、测试访问

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest()
public class ApplicationTests {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void test() throws Exception {
        // 保存字符串
        stringRedisTemplate.opsForValue().set("aaa", "111");
        Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
    }
}

通过上面这段极为简单的测试案例演示了如何通过自动配置的StringRedisTemplate对象进行Redis的读写操作,该对象从命名中就可注意到支持的是String类型。原本是RedisTemplate<K, V>接口,StringRedisTemplate就相当于RedisTemplate<String, String>的实现。

4、存储对象

这一步跟上面使用Spring一样,只需要将POJO类实现Serializable接口就可以了,我这里就贴一下测试代码:文章来源地址https://www.toymoban.com/news/detail-431525.html

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest()
public class ApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void test() throws Exception {
        User user = new User();
        user.setName("我没有三颗心脏");
        user.setAge(21);
        redisTemplate.opsForValue().set("user_1", user);
        User user1 = (User) redisTemplate.opsForValue().get("user_1");
        System.out.println(user1.getName());
    }
}
icationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void test() throws Exception {
        User user = new User();
        user.setName("我没有三颗心脏");
        user.setAge(21);
        redisTemplate.opsForValue().set("user_1", user);
        User user1 = (User) redisTemplate.opsForValue().get("user_1");
        System.out.println(user1.getName());
    }
}

到了这里,关于Redis基础知识概述的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 视频基础知识简介

    由 一组图像 组成,且图像一般为了方便传输或者减少占用空间而被 压缩 (如H264,265等格式),最终在显示设备上进行 显示 。 图像 图像由像素组成,像素又是由RGB组成,每个点的颜色由红绿蓝进行组合形成新的颜色; 分辨率 :一张图像像素点的个数,横向像素个数乘以纵向

    2024年02月14日
    浏览(41)
  • 脉冲宽度基础知识简介

    脉冲宽度是指脉冲所能达到的最大值所持续的周期时间。脉冲宽度是电子领域中一个重要的概念,它与脉冲重复间隔和占空比等参数密切相关。 脉冲宽度通常用于电信号的测量,可以用来描述脉冲的形状、幅度和宽度等特性。在雷达和电源领域中,脉冲宽度是一个重要的衡量

    2024年02月05日
    浏览(46)
  • 第1篇 目标检测概述 —(1)目标检测基础知识

    前言: Hello大家好,我是小哥谈。 目标检测是计算机视觉领域中的一项任务,旨在自动识别和定位图像或视频中的特定目标,目标可以是人、车辆、动物、物体等。目标检测的目标是从输入图像中确定目标的位置,并使用边界框将其标记出来。🎉为了让大家能够牢固地掌握

    2024年02月07日
    浏览(60)
  • MySQL 基础知识(一)之数据库和 SQL 概述

    目录 1 数据库相关概念 2 数据库的结构 ​3 SQL 概要 4 SQL 的基本书写规则 1 数据库相关概念 数据库是将大量的数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合 数据库管理系统(DBMS)是用来管理数据库的计算机系统,通过使用 DBMS,多个用户可以安全、简单

    2024年02月20日
    浏览(52)
  • 【01】基础知识:React简介与案例

    React 概述 React 是一个将数据渲染为 HTML 视图 的开源 JavaScript 库 React 由 FaceBook 开发,且开源 为什么要学习 React 1、原生 JavaScript 操作 DOM 繁琐、效率低(使用 DOM-API 操作 UI) 2、使用 JavaScript 直接操作 DOM,浏览器会进行大量的重绘重排 3、原生 JavaScript 没有组件化编码方案,

    2024年02月07日
    浏览(58)
  • Redis基础知识(安装基础指令等)

    官网: https://redis.io/ 中文地址: http://redis.cn/ 下载地址: https://redis.io/download 企业需求 高并发 高可用 高性能 海量用户 关系型数据库(如MySQL)-问题 性能瓶颈:磁盘IO 性能低下 扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群 Redis 的优势 内存存储-降低磁盘IO 次数 不存储

    2024年02月09日
    浏览(44)
  • 11. Redis基础知识

    Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能

    2024年02月14日
    浏览(36)
  • Redis基础知识(一)

    1.1 基本数据类型: String(字符串)        Hash(哈希表)         List(列表)              Set(集合)         ZSet(有序集合)         1.2 特殊类型 GEO(地理空间)        HyperLogLog(基数统计)        bitMap(位图)        bitField(位域) Stream(流)   2.1 String(字符串)         2

    2024年01月19日
    浏览(42)
  • MongoDB&Redis基础知识

    关系型数据库遵循ACID原则: 原子性 一致性 独立性 持久性 分布式系统:由多台计算机和通信的软件组件通过计算机网络连接组成,分布式系统是建立在网络之上的软件系统,因为软件的特性,所以分布式系统具有高度的内聚性和透明性。 网络和分布式系统之间的区别更多的

    2023年04月23日
    浏览(36)
  • PyTorch学习笔记(二):PyTorch简介与基础知识

      👨‍💻 作者简介: 大数据专业硕士在读,CSDN人工智能领域博客专家,阿里云专家博主,专注大数据与人工智能知识分享, 公众号: GoAI的学习小屋,免费分享书籍、简历、导图等资料,更有交流群分享AI和大数据,加群方式公众号回复“加群”或➡️点击链接。 🎉 专栏

    2023年04月09日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包