Redis

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

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

适用的场景

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

什么是缓存?
缓存的伪代码:

import org.apache.commons.lang3.RandomUtils;
import java.sql.*;
import java.util.HashMap;

/**
 * 缓存得目的就是为了减轻数据库的压力
 */
public class _01_缓存 {
    static HashMap<Integer,String> 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;
    }
}

Redis的单节点部署

  1. 下载源码包
    官网:http://redis.io
    所有版本安装包下载链接:https://download.redis.io/releases/

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

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

# 解压redis源码
tar -zxf redis-6.0.9.tar.gz

cd redis-6.0.9/
# 编译安装 迁出可执行文件
make install PREFIX=/opt/apps/redis6

# 将原来redis中的redis.conf复制出来,放在后来迁出的redis6文件夹中去
cp /opt/apps/redis/redis.conf /opt/apps/redis6/

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

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

# 环境变量
vi /etc/profile

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

source /etc/profile

# 启动redis
redis-server /opt/apps/redis6/redis.conf

# 查看是否启动成功
netstat -nltp |grep redis

# 连接到客户端
# -h 代表的是指定主机名,-p 代表的是端口号, 默认端口就是6379 --raw  中文显示乱码问题
redis-cli -h linux01 -p 6379 --raw

# 连接测试 输入ping 返回pong则成功
linux01:6379> ping
PONG

Redis数据结构

key

keys

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 列表。

MSET one 1 two 2 three 3 four 4  -- 一次设置 4 个 key
KEYS *o*
KEYS t??
KEYS t[w]*
KEYS *  -- 匹配数据库内所有 key

DEL

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

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

DUMP

DUMP key
-- 序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。

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

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

set name hello

linux01:6379> dump name
"x00x05hellotx00xb3x80x8exba1xb2Cxbb"

RESTORE

RESTORE key ttl serialized-value
-- 反序列化给定的序列化值,并将它和给定的 key 关联。
-- 参数 ttl 以毫秒为单位为 key 设置生存时间;如果 ttl 为 0 ,那么不设置生存时间。
-- RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查,如果 RDB 版本不相同或者数据不完整的话,那么 RESTORE 会拒绝进行反序列化,并返回一个错误。

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

SET greeting "hello, dumping world!"

DUMP greeting
--  "x00x15hello, dumping world!x06x00Exa0Zx82xd8rxc1xde"

RESTORE greeting-again 0 "x00x15hello, dumping world!x06x00Exa0Zx82xd8rxc1xde"

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

EXISTS

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

EXPIRE

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 

SET cache_page "www.google.com"
EXPIRE cache_page 30  -- 设置过期时间为 30 秒
TTL cache_page -- 查看剩余生存时间
EXPIRE cache_page 30000   -- 更新过期时间

TTL

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

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

PTTL

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

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

EXPIREAT

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

PEXPIREAT

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

--返回值:
--如果生存时间设置成功,返回 1
--当 key 不存在或没办法设置生存时间时,返回 0

PERSIST

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

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

RANDOMKEY

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

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

RENAME

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

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

RENAMENX

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

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

MIGRATE

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 ,否则返回相应的错误。

MOVE

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

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

String

SET

SET key value [EX seconds] [PX milliseconds] [NX|XX]
-- 将字符串值 value 关联到 key 。
-- 如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
-- 对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。

-- 可选参数
-- 从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:
-- EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。
-- PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。
-- NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 
-- XX :只在键已经存在时,才对键进行设置操作。

-- 返回值:
-- 在 Redis 2.6.12 版本以前, SET 命令总是返回 OK 。
-- 从 Redis 2.6.12 版本开始, SET 在设置操作成功完成时,才返回 OK 。
-- 如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)


-- 对不存在的键进行设置
redis 127.0.0.1:6379> SET key "value"
OK

redis 127.0.0.1:6379> GET key
"value"

-- 对已存在的键进行设置
redis 127.0.0.1:6379> SET key "new-value"
OK

redis 127.0.0.1:6379> GET key
"new-value"

-- 使用 EX 选项
redis 127.0.0.1:6379> SET key-with-expire-time "hello" EX 10086
OK

redis 127.0.0.1:6379> GET key-with-expire-time
"hello"

redis 127.0.0.1:6379> TTL key-with-expire-time
(integer) 10069

-- 使用 PX 选项
redis 127.0.0.1:6379> SET key-with-pexpire-time "moto" PX 123321
OK

redis 127.0.0.1:6379> GET key-with-pexpire-time
"moto"

redis 127.0.0.1:6379> PTTL key-with-pexpire-time
(integer) 111939


-- 使用 NX 选项
redis 127.0.0.1:6379> SET not-exists-key "value" NX
OK      -- 键不存在,设置成功

redis 127.0.0.1:6379> GET not-exists-key
"value"

redis 127.0.0.1:6379> SET not-exists-key "new-value" NX
(nil)   -- 键已经存在,设置失败

redis 127.0.0.1:6379> GEt not-exists-key
"value" # 维持原值不变


-- 使用 XX 选项
redis 127.0.0.1:6379> EXISTS exists-key
(integer) 0

redis 127.0.0.1:6379> SET exists-key "value" XX
(nil)   -- 因为键不存在,设置失败

redis 127.0.0.1:6379> SET exists-key "value"
OK      -- 先给键设置一个值

redis 127.0.0.1:6379> SET exists-key "new-value" XX
OK      -- 设置新值成功

redis 127.0.0.1:6379> GET exists-key
"new-value"


-- NX 或 XX 可以和 EX 或者 PX 组合使用
redis 127.0.0.1:6379> SET key-with-expire-and-NX "hello" EX 10086 NX
OK

redis 127.0.0.1:6379> GET key-with-expire-and-NX
"hello"

redis 127.0.0.1:6379> TTL key-with-expire-and-NX
(integer) 10063

redis 127.0.0.1:6379> SET key-with-pexpire-and-XX "old value"
OK

redis 127.0.0.1:6379> SET key-with-pexpire-and-XX "new value" PX 123321
OK

redis 127.0.0.1:6379> GET key-with-pexpire-and-XX
"new value"

redis 127.0.0.1:6379> PTTL key-with-pexpire-and-XX
(integer) 112999


-- EX 和 PX 可以同时出现,但后面给出的选项会覆盖前面给出的选项
redis 127.0.0.1:6379> SET key "value" EX 1000 PX 5000000
OK

redis 127.0.0.1:6379> TTL key
(integer) 4993  -- 这是 PX 参数设置的值

redis 127.0.0.1:6379> SET another-key "value" PX 5000000 EX 1000
OK

redis 127.0.0.1:6379> TTL another-key
(integer) 997   -- 这是 EX 参数设置的值

GET

GET key
-- 返回 key 所关联的字符串值
-- 如果 key 不存在那么返回特殊值 nil
-- 假如 key 储存的值不是字符串类型,返回一个错误,因为 GET 只能用于处理字符串值

-- 返回值:
-- 当 key 不存在时,返回 nil,否则,返回 key 的值
-- 如果 key 不是字符串类型,那么返回一个错误

-- 对不存在的 key 或字符串类型 key 进行 GET
redis> GET db
(nil)

redis> SET db redis
OK

redis> GET db
"redis"

-- 对不是字符串类型的 key 进行 GET
redis> DEL db
(integer) 1

redis> LPUSH db redis mongodb mysql
(integer) 3

redis> GET db
(error) ERR Operation against a key holding the wrong kind of value

MSET

MSET key value [key value ...]
-- 同时设置一个或多个 key-value 对。
-- 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值,如果这不是你所希望的效果,请考虑使用 MSETNX 命令:它只会在所有给定 key 都不存在的情况下进行设置操作。
-- MSET 是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key 没有改变的情况,不可能发生。


redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
OK

redis> MGET date time weather
1) "2012.3.30"
2) "11:00 a.m."
3) "sunny"


-- MSET 覆盖旧值例子
redis> SET google "google.hk"
OK

redis> MSET google "google.com"
OK

redis> GET google
"google.com"

MGET

MGET key [key ...]
-- 返回所有(一个或多个)给定 key 的值。
-- 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。

-- 返回值:一个包含所有给定 key 的值的列表。
edis> SET redis redis.com
OK

redis> SET mongodb mongodb.org
OK

redis> MGET redis mongodb mysql
1) "redis.com"
2) "mongodb.org"
3) (nil)

GETSET

GETSET key value
-- 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
-- 当 key 存在但不是字符串类型时,返回一个错误。

-- 返回值:
-- 返回给定 key 的旧值。
-- 当 key 没有旧值时,也即是, key 不存在时,返回 nil 。

redis> GETSET db mongodb    -- 没有旧值,返回 nil
(nil)

redis> GET db
"mongodb"

redis> GETSET db redis      -- 返回旧值 mongodb
"mongodb"

redis> GET db
"redis"

APPEND

APPEND key value
-- 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
-- 如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。

-- 返回值:追加 value 之后, key 中字符串的长度。

DECRBY

DECRBY key decrement
-- 将 key 所储存的值减去减量 decrement 。
-- 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECRBY 操作。
-- 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
-- 本操作的值限制在 64 位(bit)有符号数字表示之内。

DECR key
-- 将 key 中储存的数字值减一


-- 返回值:减去 decrement 之后, key 的值。

INCRBY

INCRBY key increment
-- 将 key 所储存的值加上增量 increment 。
-- 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。
-- 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
-- 本操作的值限制在 64 位(bit)有符号数字表示之内。

INCR key
-- 将 key 中储存的数字值增一

-- 返回值:加上 increment 之后, key 的值。

GETRANGE

GETRANGE key start end
-- 返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
-- 负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推。
-- GETRANGE 通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。

-- 返回值:截取得出的子字符串。

STRLEN

STRLEN key
-- 返回 key 所储存的字符串值的长度
-- 当 key 储存的不是字符串值时,返回一个错误

-- 返回值:
-- 字符串值的长度
-- 当 key 不存在时,返回 0
内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/paopaoT/p/17452831.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!