redis

Redis

什么是缓存?

缓存的伪代码:

Java
package com.doit.day01;

import org.apache.commons.lang3.RandomUtils;

import java.sql.*;
import java.util.HashMap;

/**
 *
缓存得目的就是为了减轻数据库得一个压力
 */
public class _01_
缓存 {
    static HashMap map = new HashMap<>();

    public staticd void main(String[] args) throws Exception {
        //获取mysql的连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
        for (int i = 0; i < 10000; i++) {
            //我这边再不断的访问数据库
            int id = RandomUtils.nextInt(1,10000);
            String name = getData(conn, id);
        }
    }

    public static String getData(Connection conn,int id) throws SQLException {
        String name = "";
        PreparedStatement pps = conn.prepareStatement("select name from user where id = ?");

        pps.setInt(1,id);
        String mapName = map.get(id);

        if (mapName == null){
            ResultSet resultSet = pps.executeQuery();
            while (resultSet.next()){
                name = resultSet.getString(1);
                map.put(id,name);
            }
        }else {
            return mapName;
        }
        return name;
    }
}

1.简介

Redis是一个开源(BSD许可高性能的内存存储的key-value数据库! 可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表(List)、集合(Set)、有序集合(Ordered Sets),位图(bitmap),hyperloglogsGEO等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。

1.1优点

  • 高性能: Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型:Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子性: Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
  • Redis还支持 publish/subscribe, 通知, key过期等等特性。   --这块得功能用的少
  • 可以持久化 , 数据淘汰 , 数据的过期时间   -- 可以用作一个数据库,数据比较安全
  • 分布式:  高并发  高可靠  扩展

1.2适用的场景

  1. 用来做缓存(ehcache/memcached)——redis的所有数据是放在内存中的(内存数据库)
  1. 可以在某些特定应用场景下替代传统数据库解决一些特定需求
  • 社交类的应用(共同好友,使用了某项功能的人数统计) 
  • session共享、购物车
  • 实时排行榜
  1. 可以用于实现简单的队列系统(不常用)
  1. 可以用于实现简单的订阅-发布系统
  1. 在离线批计算中,可以用redis作为外部字典库来查询(map端join)
  1. 在实时流式计算中,可以用redis作为计算过程中的中间存储,或者作为实时流式计算的最终结果存储器

2.Redis的单节点部署

2.1下载源码包

官网:http://redis.io

所有版本安装包下载链接:https://download.redis.io/releases/

注意:redis官网版本只支持linux/微软开源事业部维护了一个windows版本

1.打开官网,找到右上角的DownLoad按钮点进去

redis_第1张图片

2.向下翻,找到下面的所有Redis的版本点进去

redis_第2张图片

3.来到这个界面后找到相应的自己想要下载的版本点击就可以下载了

redis_第3张图片

注意:下载在linux上的安装包都是tar.gz结尾的

2.2编译源码

原因:redis的源码是c语言开发,编译redis源码需要安装gcc

2.2.1安装gcc

Plain Text
-- 安装centos的Extras库,它里面有一些centos的安装包
1.yum -y install centos-release-scl
-- 安装gcc,centos的默认gcc版本是4.8.5,给他升级到最新版本9.几
-- 并且安装devtoolset 用来维护开发环境
2.yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
-- 激活对应的devtoolset
3.scl enable devtoolset-9 bash
-- 配置环境变量
4.echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile
-- source下环境变量使环境变量生效
5.source /etc/profile
-- 安装完成之后查看是否安装成功
6.gcc -v   //查看版本号,如果有版本号出现代表安装成功
-- 最下面一行出现这个
gcc version 9.3.1 20200408 (Red Hat 9.3.1-2) (GCC)

2.2.2解压redis源码

Shell
tar -zxf redis-6.0.9.tar.gz

2.2.3编译安装

Shell
[root@doitedu03 ~]# cd redis-6.0.9/
#
编译
[root@doitedu03 redis-6.0.9]# make
# 迁出可执行文件
[root@doitedu03 redis-6.0.9]#
make install PREFIX=/opt/apps/redis6

2.2.4准备reids的配置文件

Plain Text
将原来redis中的redis.conf复制出来,放在后来迁出的redis6文件夹中去
-- 复制的命令
cp /opt/app/redis/redis.conf /opt/app/redis6/

修改复制过来的配置文件
vi redis.conf
修改的第一个地方:
bind 127.0.0.1 -- 原来监听的端口是本机,后面我们要搭建集群,远程连接,本地显然是不合适

bind linux01  -- 改成集群里面的地址

修改的第二个地方: daemonize 后台运行的意思,如果是no,就是前台启动,改成yes,后台启动,方便一点
daemonize no  -- 原来是no
daemonize yes -- 改成yes

2.2.5配置系统环境变量

Plain Text
vi /etc/profile

# REDIS_HOME
export REDIS_HOME=/opt/app/redis6
export PATH=$PATH:$REDIS_HOME/bin

source /etc/profile

2.3启动redis的服务

Shell
-- 进入到redis6的bin目录下执行,其实配置了环境变量,在哪执行都一样
[root@linux01 /]# ./redis-server /opt/app/redis6/redis.conf

-- 查看redis的服务是否已经启动成功
[root@linux01 /]# netstat -nltp |grep redis
tcp        0      0 192.168.232.3:6379      0.0.0.0:*               LISTEN      6040/redis-server l

 

2.4连接到客户端

Shell
-- 进入到redis6的bin目录下执行,其实配置了环境变量,在哪执行都一样
[root@linux01 bin]# redis-cli
-- 报错了:
Could not connect to Redis at 127.0.0.1:6379: Connection refused

原因是我们之前修改了它监听的主机,将127.0.0.1 修改成了linux01
redis-cli -h linux01 -p 6379

解释:-h 代表的是指定主机名,-p 代表的是端口号,我们没有修改他的端口号,默认就是6379,所以也可以不写


-- 连接测试  你给他一个ping  他给你一个pong 就代表连接成功了  --raw  中文显示乱码问题
[root@linux01 /]# redis-cli -h linux01  --raw
linux01:6379> ping
PONG
linux01:6379>

3.Redis数据结构

3.1  key :   key

3.1.1 keys

Shell
KEYS pattern
查找所有符合给定模式 pattern 的 key 。
KEYS *             匹配数据库中所有 key 。
KEYS h?llo         匹配 hello , hallo 和 hxllo 等。   占一个字符
KEYS h*llo         匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo      匹配 hello 和 hallo ,但不匹配 hillo 。

返回值:符合给定模式的 key 列表。

示例:

Shell
redis> MSET one 1 two 2 three 3 four 4  # 一次设置 4 个 key
OK

redis> KEYS *o*
1) "four"
2) "two"
3) "one"

redis> KEYS t??
1) "two"

redis> KEYS t[w]*
1) "two"

redis> KEYS *  # 匹配数据库内所有 key
1) "four"
2) "three"
3) "two"
4) "one"

3.1.2 DEL

Shell
DEL key [key ...]
删除给定的一个或多个 key 。
不存在的 key 会被忽略。

返回值:被删除 key 的数量。

示例:

Shell
删除单个 key
redis> SET name zhangsan
OK

redis> DEL name
(integer) 1

# 删除一个不存在的 key

redis> EXISTS phone
(integer) 0

redis> DEL phone # 失败,没有 key 被删除
(integer) 0


# 同时删除多个 key

redis> SET name "redis"
OK

redis> SET type "key-value store"
OK

redis> SET website "redis.com"
OK

redis> DEL name type website
(integer) 3

3.1.3 DUMP

Plain Text
DUMP key
序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。
序列化生成的值有以下几个特点:
它带有 64 位的校验和,用于检测错误,
RESTORE 在进行反序列化之前会先检查校验和。
值的编码格式和 RDB 文件保持一致。
RDB 版本会被编码在序列化值当中,如果因为 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。
序列化的值不包括任何生存时间信息。

返回值:
如果 key 不存在,那么返回 nil 。
否则,返回序列化之后的值。

示例:

Shell
linux01:6379> set name hello
OK

linux01:6379> dump name
"\x00\x05hello\t\x00\xb3\x80\x8e\xba1\xb2C\xbb"

--
如果序列化的key不存在美酒返回nil
redis> DUMP not-exists-key
(nil)

3.1.4RESTORE

Plain Text
RESTORE key ttl serialized-value
反序列化给定的序列化值,并将它和给定的 key 关联。
参数 ttl 以毫秒为单位为 key 设置生存时间;如果 ttl 为 0 ,那么不设置生存时间。

RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查,如果 RDB 版本不相同或者数据不完整的话,那么 RESTORE 会拒绝进行反序列化,并返回一个错误。

返回值:
如果反序列化成功那么返回 OK ,否则返回一个错误。

示例:

Shell
redis> SET greeting "hello, dumping world!"
OK

redis> DUMP greeting
"\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"

redis> RESTORE greeting-again 0 "\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"
OK

redis> GET greeting-again
"hello, dumping world!"

redis> RESTORE fake-message 0 "hello moto moto blah blah"   ;
使用错误的值进行反序列化
(error) ERR DUMP payload version or checksum are wrong

3.1.5EXISTS

Plain Text
EXISTS key
检查给定 key 是否存在。
返回值:若 key 存在,返回 1 ,否则返回 0 。

示例:

Shell
redis> SET db "redis"
OK

redis> EXISTS db
(integer) 1

redis> DEL db
(integer) 1

redis> EXISTS db
(integer) 0

3.1.6EXPIRE

Plain Text
EXPIRE key seconds
为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。

更新生存时间
可以对一个已经带有生存时间的 key 执行
EXPIRE 命令,新指定的生存时间会取代旧的生存时间。

过期时间的精确度
在 Redis 2.4 版本中,过期时间的延迟在 1 秒钟之内 —— 也即是,就算 key 已经过期,但它还是可能在过期之后一秒钟之内被访问到,而在新的 Redis 2.6 版本中,延迟被降低到 1 毫秒之内。

返回值:
设置成功返回 1 。
当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0

示例:

Shell
redis> SET cache_page "www.google.com"
OK

redis> EXPIRE cache_page 30  #
设置过期时间为 30 秒
(integer) 1

redis> TTL cache_page    # 查看剩余生存时间
(integer) 23

redis> EXPIRE cache_page 30000   # 更新过期时间
(integer) 1

redis> TTL cache_page
(integer) 29996

3.1.7TTL

Plain Text
TTL key
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。

返回值:
当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以秒为单位,返回 key 的剩余生存时间。

示例:

Shell
# 不存在的 key

redis> FLUSHDB
OK

redis> TTL key
(integer) -2


# key 存在,但没有设置剩余生存时间

redis> SET key value
OK

redis> TTL key
(integer) -1


# 有剩余生存时间的 key

redis> EXPIRE key 10086
(integer) 1

redis> TTL key
(integer) 10084

3.1.8EXPIREAT

Plain Text
EXPIREAT key timestamp
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。
不同在于
EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。

示例:

Shell
redis> SET cache www.google.com
OK

redis> EXPIREAT cache 1355292000     #
这个 key 将在 2012.12.12 过期
(integer) 1

redis> TTL cache
(integer) 45081860

3.1.9PERSIST

Plain Text
PERSIST key
移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。

返回值:
当生存时间移除成功时,返回 1 .
如果 key 不存在或 key 没有设置生存时间,返回 0 。

示例:

Shell
redis> SET mykey "Hello"
OK

redis> EXPIRE mykey 10  #
为 key 设置生存时间
(integer) 1

redis> TTL mykey
(integer) 10

redis> PERSIST mykey    # 移除 key 的生存时间
(integer) 1

redis> TTL mykey
(integer) -1

3.1.10PEXPIREAT

Plain Text
PEXPIREAT key milliseconds-timestamp
这个命令和 EXPIREAT 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 EXPIREAT 那样,以秒为单位。

返回值:
如果生存时间设置成功,返回 1 。
当 key 不存在或没办法设置生存时间时,返回 0 。(查看
EXPIRE 命令获取更多信息)

示例:

Shell
redis> SET mykey "Hello"
OK

redis> PEXPIREAT mykey 1555555555005
(integer) 1

redis> TTL mykey           # TTL
返回秒
(integer) 223157079

redis> PTTL mykey          # PTTL 返回毫秒
(integer) 223157079318

3.1.11PTTL

Plain Text
PTTL key
这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。

返回值:
当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以毫秒为单位,返回 key 的剩余生存时间。

 

Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1

示例:

Shell
# 不存在的 key

redis> FLUSHDB
OK

redis> PTTL key
(integer) -2


# key 存在,但没有设置剩余生存时间

redis> SET key value
OK

redis> PTTL key
(integer) -1


# 有剩余生存时间的 key

redis> PEXPIRE key 10086
(integer) 1

redis> PTTL key
(integer) 6179

3.1.12MIGRATE

Plain Text
MIGRATE host port key destination-db timeout [COPY] [REPLACE]
将 key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功, key 保证会出现在目标实例上,而当前实例上的 key 会被删除。
这个命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到以下任意结果发生:迁移成功,迁移失败,等到超时。
命令的内部实现是这样的:它在当前实例对给定 key 执行
DUMP 命令 ,将它序列化,然后传送到目标实例,目标实例再使用 RESTORE 对数据进行反序列化,并将反序列化所得的数据添加到数据库中;当前实例就像目标实例的客户端那样,只要看到 RESTORE 命令返回 OK ,它就会调用 DEL 删除自己数据库上的 key 。
timeout 参数以毫秒为格式,指定当前实例和目标实例进行沟通的最大间隔时间。这说明操作并不一定要在 timeout 毫秒内完成,只是说数据传送的时间不能超过这个 timeout 数。

可选项:
COPY :不移除源实例上的 key 。
REPLACE :替换目标实例上已存在的 key 。

返回值:迁移成功时返回 OK ,否则返回相应的错误。

示例:

先启动两个 Redis 实例,一个使用默认的 6379 端口,一个使用 7777 端口。

Shell
$ ./redis-server --port 7777 &
[2] 3560

...

然后用客户端连上 6379 端口的实例,设置一个键,然后将它迁移到 7777 端口的实例上:

Shell
$ ./redis-cli

redis 127.0.0.1:6379> flushdb
OK

redis 127.0.0.1:6379> SET greeting "Hello from 6379 instance"
OK

redis 127.0.0.1:6379> MIGRATE 127.0.0.1 7777 greeting 0 1000
OK

redis 127.0.0.1:6379> EXISTS greeting      #
迁移成功后 key 被删除
(integer) 0

使用另一个客户端,查看 7777 端口上的实例:

Shell
$ ./redis-cli -p 7777

redis 127.0.0.1:7777> GET greeting
"Hello from 6379 instance"

redis_第4张图片

3.1.13MOVE

Plain Text
MOVE key db
将当前数据库的 key 移动到给定的数据库 db 当中。
如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。
因此,也可以利用这一特性,将
MOVE 当作锁(locking)原语(primitive)。

返回值:移动成功返回 1 ,失败则返回 0 。

示例:

Shell
# key 存在于当前数据库

redis> SELECT 0                             # redis默认使用数据库 0,为了清晰起见,这里再显式指定一次。
OK

redis> SET song "secret base - Zone"
OK

redis> MOVE song 1                          # 将 song 移动到数据库 1
(integer) 1

redis> EXISTS song                          # song 已经被移走
(integer) 0

redis> SELECT 1                             # 使用数据库 1
OK

redis:1> EXISTS song                        # 证实 song 被移到了数据库 1 (注意命令提示符变成了"redis:1",表明正在使用数据库 1)
(integer) 1


# 当 key 不存在的时候

redis:1> EXISTS fake_key
(integer) 0

redis:1> MOVE fake_key 0                    # 试图从数据库 1 移动一个不存在的 key 到数据库 0,失败
(integer) 0

redis:1> select 0                           # 使用数据库0
OK

redis> EXISTS fake_key                      # 证实 fake_key 不存在
(integer) 0

# 当源数据库和目标数据库有相同的 key 时

redis> SELECT 0                             # 使用数据库0
OK
redis> SET favorite_fruit "banana"
OK

redis> SELECT 1                             # 使用数据库1
OK
redis:1> SET favorite_fruit "apple"
OK

redis:1> SELECT 0                           # 使用数据库0,并试图将 favorite_fruit 移动到数据库 1
OK

redis> MOVE favorite_fruit 1                # 因为两个数据库有相同的 key,MOVE 失败
(integer) 0

redis> GET favorite_fruit                   # 数据库 0 的 favorite_fruit 没变
"banana"

redis> SELECT 1
OK

redis:1> GET favorite_fruit                 # 数据库 1 的 favorite_fruit 也是
"apple"

3.1.14RANDOMKEY

Plain Text
RANDOMKEY
从当前数据库中随机返回(不删除)一个 key 。

返回值:
当数据库不为空时,返回一个 key 。
当数据库为空时,返回 nil 。

示例:

Shell
# 数据库不为空

redis> MSET fruit "apple" drink "beer" food "cookies"   # 设置多个 key
OK

redis> RANDOMKEY
"fruit"

redis> RANDOMKEY
"food"

redis> KEYS *    # 查看数据库内所有key,证明 RANDOMKEY 并不删除 key
1) "food"
2) "drink"
3) "fruit"


# 数据库为空

redis> FLUSHDB  # 删除当前数据库所有 key
OK

redis> RANDOMKEY
(nil)

3.1.15RENAME

Plain Text
RENAME key newkey
将 key 改名为 newkey 。
当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
当 newkey 已经存在时,
RENAME 命令将覆盖旧值。

返回值:
改名成功时提示 OK ,失败时候返回一个错误。

示例:

Shell
# key 存在且 newkey 不存在

redis> SET message "hello world"
OK

redis> RENAME message greeting
OK

redis> EXISTS message               # message 不复存在
(integer) 0

redis> EXISTS greeting              # greeting 取而代之
(integer) 1


# 当 key 不存在时,返回错误

redis> RENAME fake_key never_exists
(error) ERR no such key


# newkey 已存在时, RENAME 会覆盖旧 newkey

redis> SET pc "lenovo"
OK

redis> SET personal_computer "dell"
OK

redis> RENAME pc personal_computer
OK

redis> GET pc
(nil)

redis:1> GET personal_computer      # 原来的值 dell 被覆盖了
"lenovo"

3.1.16RENAMENX

Plain Text
RENAMENX key newkey
当且仅当 newkey 不存在时,将 key 改名为 newkey 。
当 newkey 存在时,返回一个0。

返回值:
修改成功时,返回 1 。
如果 newkey 已经存在,返回 0 。

示例:

Shell
# newkey 不存在,改名成功

redis> SET player "MPlyaer"
OK

redis> EXISTS best_player
(integer) 0

redis> RENAMENX player best_player
(integer) 1


# newkey存在时,失败

redis> SET animal "bear"
OK

redis> SET favorite_animal "butterfly"
OK

redis> RENAMENX animal favorite_animal
(integer) 0

redis> get animal
"bear"

redis> get favorite_animal
"butterfly"

你可能感兴趣的:(redis,java,mybatis)