Redis系列:Redis的概述与安装

Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库。

本篇内容包括:Redis 简介(为什么快?为什么单线程?优点,缺点等),Redis 在 Java Web 中的应用,Redis 安装(Win、Linux、Mac 场景下的安装)等内容


文章目录

    • 一、Redis 简介
        • 1、Redis为什么快呢?
        • 2、Redis为何选择单线程?
        • 3、那为什么Redis6.0之后又改用多线程呢?
        • 4、Redis的优势
        • 5、Redis的缺点
    • 二、Redis 在 Java Web 中的应用
        • 1、Redis 的使用场景
        • 2、缓存
        • 3、高速读/写的场合
    • 三、Redis 安装
        • 1、Windows 下安装
        • 2、Linux 下安装
        • 3、Mac 下安装(使用Homebrew)


一、Redis 简介

Redis 是 C 语言开发的一个开源的(遵从 BSD 协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。

它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库。是一种基于内存的数据库,并且提供一定的持久化功能。

Redis 作为一个内存数据库:性能优秀,数据在内存中,读写速度非常快,支持并发 10W QPS。单进程单线程,是线程安全的,采用 IO 多路复用机制。丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。支持数据持久化。可以将内存中数据保存在磁盘中,重启时加载。主从复制,哨兵,高可用。可以用作分布式锁。可以作为消息中间件使用,支持发布订阅。

1、Redis为什么快呢?

redis的速度非常的快,单机的redis就可以支撑每秒10几万的并发,相对于mysql来说,性能是mysql的几十倍。速度快的原因主要有几点:

  1. 完全基于内存操作
  2. C语言实现,优化过的数据结构,基于几种基础的数据结构,redis做了大量的优化,性能极高
  3. 使用单线程,无上下文的切换成本
  4. 基于非阻塞的IO多路复用机制

2、Redis为何选择单线程?

  • 避免过多的上下文切换开销。程序始终运行在进程中单个线程内,没有多线程切换的场景。
  • 避免同步机制的开销:如果 Redis选择多线程模型,需要考虑数据同步的问题,则必然会引入某些同步机制,会导致在操作数据过程中带来更多的开销,增加程序复杂度的同时还会降低性能。
  • 实现简单,方便维护:如果 Redis使用多线程模式,那么所有的底层数据结构的设计都必须考虑线程安全问题,那么 Redis 的实现将会变得更加复杂。

3、那为什么Redis6.0之后又改用多线程呢?

Redis 使用多线程并非是完全摒弃单线程,Redis 还是使用单线程模型来处理客户端的请求,只是使用多线程来处理数据的读写和协议解析,执行命令还是使用单线程。

这样做的目的是因为redis的性能瓶颈在于网络 IO 而非 CPU,使用多线程能提升 IO 读写的效率,从而整体提高 Redis 的性能。

4、Redis的优势

  • Redis支持保存多种数据结构(支持string,list,set,sorted set,hash),其单个value的最大限制是1GB,因此Redis可以用来实现很多有用的功能;
  • 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB;
  • Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用;
  • Redis可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障的时 候,内存中的数据不会“丢失”;
  • 除了上述功能以外,Redis还提供了键过期、发布订阅、事务、流水线、Lua脚本等附加功能。

5、Redis的缺点

Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。

总之,如果在合适的场景使用好Redis,它就会像一把瑞士军刀一样所向披靡、无往不利!!!


二、Redis 在 Java Web 中的应用

1、Redis 的使用场景

Redis 根据使用数据类型的不同,对应的使用场景有很多,例如:

  1. 缓存(String / Hash 类型):缓存如用户信息,视频信息等;
  2. 分布式锁(String 类型):setnx 方法,「key不存在才插入」,可以用它来实现分布式锁;
  3. 计数器(String 类型):incr/decr 方法,自增自减,由于是原子性,可以用来计数统计浏览数、点赞数等;
  4. 限制请求次数(String 类型):也是利用 incr 方法,限制请求次数访问者的 ip 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false;
  5. 数据共享分布式(String 类型):因为 Redis 是分布式的独立服务,可以在多个应用之间共享,所有可以实现需要例如分布式 Session;
  6. 购物车(Hash 类型):类似存储商品信息,大 key 为商家 id,小 key 是商品 id 即 goodsId,value 为该 goodsId 的详细信息;
  7. 消息队列(List / Stream 类型):二者都可以实现消息队列,而 Redis5.0 新增的 Stream,解决了 List 实现的消息队列不能持久化和不能重复消费的问题;
  8. 点赞、踩、收藏(Set 类型):Set 集合无需、不可重复,可以保证一个用户只能点一个赞;
  9. 共同关注(Set 类型):Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等;
  10. 抽奖活动(Set 类型):存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次;
  11. 排行榜(ZSet 类型):有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序,所以可以用作排行榜功能的实现;
  12. 此外利用 Redis 的特殊数据类型也可以实现一些相应的功能:Bit 位运算用来签到统计、HyperLogLogs 统计基数用来百万级网络 UV,还有 GEO 地理位置、用来打车等;

2、缓存

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

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

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

  • 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存;
  • 该业务数据是读操作多,还是写操作多?如果写操作多,频繁需要写入数据库,也没有必要使用缓存;
  • 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要。

在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!

使用 Redis 作为缓存的读取逻辑如下图所示:

Redis缓存读取逻辑

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

  1. 当第一次读取数据的时候,读取 Redis 的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入 Redis 中;
  2. 当第二次以及以后需要读取数据时,就会直接读取 Redis,读到数据后就结束了流程,这样速度就大大提高了。

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

使用 Redis 作为缓存的写入逻辑如下图所示:

Redis缓存写入逻辑.png

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

3、高速读/写的场合

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

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

Redis高速读写的场合

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

  1. 当一个请求到达服务器时,只是把业务数据在 Redis 上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速响应的需求;
  2. 但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完 Redis 的读/写之后,会去判断该高速读/写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为 0 时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

三、Redis 安装

1、Windows 下安装

  1. 官方没有 Windows版本的 Redis

  2. Windows版本下载地址:https://github.com/MicrosoftArchive/redis/releases,下载 Redis-x64-3.2.100.msi

  3. 双击刚下载好的msi格式的安装包(Redis-x64-3.2.100.msi):

    1. 开始安装

    2. 选择“同意协议”,点击下一步继续:

    3. 选择“添加Redis目录到环境变量PATH中”,这样方便系统自动识别Redis执行文件在哪里:

    4. 端口号可保持默认的6379,并选择防火墙例外,从而保证外部可以正常访问Redis服务:

    5. 设定最大值为100M。作为实验和学习,100M足够了:

  4. 右击“计算机”>选择“管理”。在左侧栏中依次找到并点击“计算机管理(本地)”> 服务和应用程序 > 服务。再在右侧找到Redis名称的服务,查看启动情况。如未启动,则手动启动之。正常情况下,服务应该正常启动并运行了

  5. 最后来测试一下 Redis 是否正常提供服务。进入 Redis 的目录使用cmd。输入redis-cli并回车。(redis-cli是客户端程序)如图正常提示进入,并显示正确端口号,则表示服务已经启动

    批注 2021-07-08 1935126

  6. 实际测试一下读写。输入set mykey1 "I love you all!"并回车,用来保存一个键值。再输入get mykey1,获取刚才保存的键值

2、Linux 下安装

  1. Redis官网 https://redis.io/ 直接点击下载得到:redis-6.2.4.tar.gz

  2. 把 redis-6.2.4.tar.gz 移动到/usr/local/ 目录下 : mv redis-6.2.4.tar.gz /usr/local/

  3. 解压 redis-6.2.4.tar.gz : tar -zxvf redis-6.2.4.tar.gz

  4. 由于redis是由C语言编写的,它的运行需要C环境,因此我们需要先安装gcc : yum install gcc-c++

  5. 进入到 /usr/local/redis-6.2.4/ 目录下,进行编译与安装 :cd redis-6.2.4makecd ./srcmake install

  6. Redis不是默认后台启动的,需要求改一下配置文件:vi redis.confdaemonize 属性改为 yes

  7. 编辑 redis.conf配置文件,开启redis远程访问服务:

    • 配置文件中的 bind 127.0.0.1 这一行给注释掉,这里的bind指的是只有指定的网段才能远程访问这个redis,注释掉后,就没有这个限制了
    • 配置文件中的 protected-mode 设置成 no(默认是设置成yes的, 防止了远程访问,在redis3.2.3版本后)
  8. 启动redis服务: redis-server redis.conf

  9. 启动redis客户端服务:redis-cli -p 6379

  10. 打开RedisDesktopManager,测试服务是否开启 以及 是否可以远程访问Redis\

    批注 2021-07-08 204649

3、Mac 下安装(使用Homebrew)

  1. 没有安装Homebrew,首先安装npm国内的吧,快一些:/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)";
  2. 使用Homebrew安装命令:brew install redis
  3. 查看安装及配置文件位置:
    • Homebrew安装的软件会默认在/usr/local/Cellar/路径下
    • redis的配置文件redis.conf存放在/usr/local/etc路径下
  4. 启动redis服务:redis-server /usr/local/etc/redis.confbrew services start redisredis-server
  5. 查看redis服务进程:ps axu | grep redis
  6. redis-cli连接redis服务,redis默认端口号6379,默认auth为空:redis-cli -h 127.0.0.1 -p 6379

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装LibreOffice和字体

#/bin/bash # Check if user is root if [ $(id -u) ! "0" ]; thenecho "Error: You must be root to run this script, please use root"exit 1 fi echo 安装LibreOffice cd /home/ tar -zxvf LibreOffice_6.3.3_Linux_x86-64_rpm.tar.gz cd /home/LibreO…

xtrabackup备份脚本

#!/bin/sh #备份主机 remote_ip100.0.132.160 Master_ip100.20.132.158 VIP100.20.132.166 #备份用户 userroot #密码 password00000 # 返回年月日 backup_datedate %F # 返回时分秒 backup_timedate %H-%M-%S # 返回今天是这周的第几天 backup_week_daydate %u backup_ok0 #备…

Redis系列:使用Redis实现分布式锁及相关问题

分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。 本篇内容包括:关于 Redis 与 分布式锁&…

Redis系列:Redis持久化机制与Redis事务

Redis 是个基于内存的数据库。那服务一旦宕机,内存中数据必将全部丢失。所以丢失数据的恢复对于 Redis 是十分重要的,我们首先想到是可以从数据库中恢复,但是在由 Redis 宕机时(说明相关工作正在运行)且数据量很大情况…

Java基础:Java程序设计环境

按应用范围,Java 可分为 3 个体系,即 Java SE、Java EE 和 Java ME。Java 语言的开发运行,也离不开 Java 语言的运行环境 JRE。没有 JRE 的支持,Java 语言便无法运行。当然,如果还想编译 Java 程序,搞搞小开…

负载均衡策略

轮循均衡(Round Robin):每一次来自网络的请求轮流分配给内部中的服务器,从1至N然后重新开始。此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况。 我们的业务web服务器都是同样配置…

Java基础:Java数据类型

Java 是一种强类型语言,这就意味着必须为每一个变量声明一种类型。在 Java 中基本数据类型共有 8 种,包括 4 种整型、2 种浮点型、1 种用于表现 Unicode 编码的字符单元的字符类型 char 和一种用于表示真值的 boolean 类型 ~ 本篇主要记录内容包括&#…

TCP连接的建立与终止

TCP连接的建立与终止 1.三次握手 TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方…

日常问题:MySQL排序字段数据相同不能分页问题

【问题日期】 2022-11-14 22:45:12 【问题描述】 MySQL 排序字段数据相同不能分页问题:在分页查询数据时,按创建时间排序,由于数据是批量创建的,导致部分数据创建时间一样,而此时分页查询数据,翻页后出现…

数据缺失值处理

数据缺失值处理 In [1]: import pandas as pd import numpy as np from sklearn.ensemble import RandomForestRegressor,RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.impute import SimpleImputer In [2]: df pd.DataFrame() df[…

Java基础:Java数字类型

Java 中包含多种运算符:算数运算符、关系运算符、逻辑运算符、位运算符。在 Math 类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。要生成一个随机数,可以使用 Random 对象。 ~ 本篇主要…

Java基础:Java流程控制

块(即复合语句)是指由一对大括号括起来的若干条简单的 Java 语句。块确定了变量的作用域。一个块可以嵌套在另一个块中。但是,不能在嵌套的两个块中声明同名的变量。使用块(有时称为复合语句)可以在Java程序结构中原本…

Java基础:Java类与对象

面向对象程序设计(简称OOP)是当今主流的程序设计范型,它已经取代了20世纪70年代的“结构化”过程化程序设计开发技术。Java是完全面向对象的,必须熟悉OOP才能够编写Java程序。面向对象的程序是由对象组成的,每个对象包…

SVN备份脚本

#!/bin/bash #svn全量备份脚本 wwytcode_path/home/wwytcode/project backup_path/home/bak Datedate %Y%m%d cd $backup_path echo date >> $back_path/svn_backup.log svnversionsvnlook youngest $wwytcode_path svnadmin dump --revision 0:$svnversion $wwytcode_pa…

Java基础:Java面向对象

面向过程的优点是性能比面向对象高,不需要面向对象的实例化;缺点是不容易维护、复用和扩展。面向对象的优点是具有封装、继承、多态的特性,因而容易维护、复用和扩展,可以设计出低耦合的系统;缺点是由于需要实例化对象…

薪资生成

import openpyxl from openpyxl.styles import Font,Alignment,Side,Border#设置字体样式 fontFont(name宋体,size20,boldTrue) font2Font(name宋体,size12,boldTrue) alignmentAlignment(horizontalcenter,verticalcenter,wrap_textTrue) sideSide(stylethin ,color000000) …

Java基础:Java抽象接口

在Java中,一个没有方法体的方法应该定义为抽象方法,而如果一个类中含有抽象方法,则该类必须定义为一个抽象类。接口是功能的集合,同样可看做是一种特殊的数据类型,是比抽象类更为抽象的类,接口只描述所应该…

13 张图带你学懂 Kubernetes Service(转载)

在 Kubernetes 中 Service 主要有4种不同的类型,其中的 ClusterIP 是最基础的,如下图所示: 当我们创建一个 NodePort 的 Service 时,它也会创建一个 ClusterIP,而如果你创建一个 LoadBalancer,它就会创建一…

Java基础:Java异常机制

异常是程序运行过程中出现的错误。Java 把异常当作对象来处理,把异常信息封装成了一个类,并定义一个基类java.lang.Throwable作为所有异常的超类。Throwable : 它是所有错误与异常的超类(祖宗类),有两个子类 Error 和 Exception。…

JavaWeb:Servlet的应用及接口介绍

广义的 Servlet 泛指在服务器上运行的 Java 程序,但是这个 Java 程序,并不能独立运行(因为 Servlet 没有 main 方法),需要部署在相应的 Servlet 容器中,比如 Tomcat 和 Jetty。Servlet 主要功能在于交互式地…