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过期等等特性。 –这块得功能用的少
- 可以持久化 , 数据淘汰 , 数据的过期时间 — 可以用作一个数据库,数据比较安全
- 分布式: 高并发 高可靠 扩展
适用的场景
- 用来做缓存(ehcache/memcached)——redis的所有数据是放在内存中的(内存数据库)
- 可以在某些特定应用场景下替代传统数据库解决一些特定需求
- 社交类的应用(共同好友,使用了某项功能的人数统计)
- session共享、购物车
- 实时排行榜
- 可以用于实现简单的队列系统(不常用)
- 可以用于实现简单的订阅-发布系统
- 在离线批计算中,可以用redis作为外部字典库来查询(map端join)
- 在实时流式计算中,可以用redis作为计算过程中的中间存储,或者作为实时流式计算的最终结果存储器
什么是缓存?
缓存的伪代码:
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; }}
Redis的单节点部署
下载源码包
官网:http://redis.io
所有版本安装包下载链接:https://download.redis.io/releases/编译源码
原因: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# 激活对应的devtoolsetscl 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.gzcd 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 # 原来是nodaemonize yes # 改成yes# 环境变量vi /etc/profile# REDIS_HOMEexport REDIS_HOME=/opt/app/redis6export PATH=$PATH:$REDIS_HOME/binsource /etc/profile# 启动redisredis-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> pingPONG
Redis数据结构keykeys
KEYS pattern-- 查找所有符合给定模式 pattern 的 keyKEYS * -- 匹配数据库中所有 keyKEYS 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 个 keyKEYS *o*KEYS t??KEYS t[w]*KEYS * -- 匹配数据库内所有 key
DEL
DEL key [key ...]-- 删除给定的一个或多个 key 。-- 不存在的 key 会被忽略。-- 返回值:被删除 key 的数量。### DUMPPlain TextDUMP 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 hellolinux01:6379> dump name"\x00\x05hello\t\x00\xb3\x80\x8e\xba1\xb2C\xbb"
RESTORE
RESTORE key ttl serialized-value-- 反序列化给定的序列化值,并将它和给定的 key 关联。-- 参数 ttl 以毫秒为单位为 key 设置生存时间;如果 ttl 为 0 ,那么不设置生存时间。-- RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查,如果 RDB 版本不相同或者数据不完整的话,那么 RESTORE 会拒绝进行反序列化,并返回一个错误。-- 返回值:-- 如果反序列化成功那么返回 OK ,否则返回一个错误。SET greeting "hello, dumping world!"DUMP greeting-- "\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"RESTORE greeting-again 0 "\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"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 。
StringSET
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"OKredis 127.0.0.1:6379> GET key"value"-- 对已存在的键进行设置redis 127.0.0.1:6379> SET key "new-value"OKredis 127.0.0.1:6379> GET key"new-value"-- 使用 EX 选项redis 127.0.0.1:6379> SET key-with-expire-time "hello" EX 10086OKredis 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 123321OKredis 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" NXOK -- 键不存在,设置成功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) 0redis 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" XXOK -- 设置新值成功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 NXOKredis 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) 10063redis 127.0.0.1:6379> SET key-with-pexpire-and-XX "old value"OKredis 127.0.0.1:6379> SET key-with-pexpire-and-XX "new value" PX 123321OKredis 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 5000000OKredis 127.0.0.1:6379> TTL key(integer) 4993 -- 这是 PX 参数设置的值redis 127.0.0.1:6379> SET another-key "value" PX 5000000 EX 1000OKredis 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 进行 GETredis> GET db(nil)redis> SET db redisOKredis> GET db"redis"-- 对不是字符串类型的 key 进行 GETredis> DEL db(integer) 1redis> LPUSH db redis mongodb mysql(integer) 3redis> 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"OKredis> MGET date time weather1) "2012.3.30"2) "11:00 a.m."3) "sunny"-- MSET 覆盖旧值例子redis> SET google "google.hk"OKredis> MSET google "google.com"OKredis> GET google"google.com"
MGET
MGET key [key ...]-- 返回所有(一个或多个)给定 key 的值。-- 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。-- 返回值:一个包含所有给定 key 的值的列表。edis> SET redis redis.comOKredis> SET mongodb mongodb.orgOKredis> MGET redis mongodb mysql1) "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