先测试能连接到 redis 服务器,返回 PONG,表示 redis 服务运行正常
将字符串值 value 设置到 key 中
语法:set key value
查看已经插入的 key
向已经存在的 key 设置新的 value,会覆盖原来的值
获取 key 中设置的字符串值
语法:get key
例如:获取 username 这个key 对应的 value
将 key 中储存的数字值加 1,如果 key 不存在,则 key 的值先被初始化为 0 再执行 incr 操作(只能对数字类型的数据操作)
语法:incr key
例1:操作 key 值增加 1
例2:对非数字的值操作是不行的
将 key 中储存的数字值减 1,如果 key 不存在,那么 key 的值先被初始化为 0 再执行 decr 操作(只能对数字类型的数据操作)
语法:decr key
语法:append key value
说明:如果 key 存在,则将 value 追加到 key 原来旧值的末尾。如果 key 不存在,则将 key 设置值为 value
返回值:追加字符串之后的总长度
例1:追加内容到存在的 key
例2:追加到不存在的 key,同 set key value
语法:strlen key
说明:返回 key 所储存的字符串值的长度
返回值:
例1:计算存在 key 的字符串长度
设置中文 set k1 中文长度,按字符个数计算
语法:getrange key start end
作用:获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end,负数表示从字符串的末尾开始, -1 表示最后一个字符
返回值:截取的子字符串
使用的字符串 key:index,value: 20hello
语法:setrange key offset value
说明:用 value 覆盖(替换)key 的存储的值从 offset 开始,不存在的 key 做空白字符串
返回值:修改后的字符串的长度
语法:mset key value [key value…]
说明:同时设置一个或多个 key-value 对
返回值:OK
语法:mget key [key …]
作用:获取所有(一个或多个)给定 key 的值
返回值:包含所有 key 的列表
例1:返回多个 key 的存储值
例2:返回不存在的 key
redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
语法:hset hash 表的 key field value
作用:将哈希表 key 中的域 field 的值设为 value ,如果 key 不存在,则新建 hash 表,行赋值,如果有 field,则覆盖值。
返回值:
语法:hget key field
作用:获取哈希表 key 中给定域 field 的值
返回值:field 域的值,如果 key 不存在或者 field 不存在返回 nil
例1:获取存在 key 值的某个域的值
例2:获取不存在的 field
语法:hmset key field value [field vale…]
说明:同时将多个 field-value(域值)设置到哈希表 key 中,此命令会覆盖已经存在的 field。hash 表 key 不存在,创建空的 hash 表,执行 hmset。
返回值:设置成功返回 ok,如 果失败返回一个错误
例:同时设置多个 field-value
使用 redis-desktop- manager工具查看 hash 表 website 的数据结构
语法:hmget key field [field…]
作用:获取哈希表 key 中一个或多个给定域的值
返回值:返回和 field 顺序对应的值,如果 field 不存在,返回 nil
语法:hgetall key
作用:获取哈希表 key 中所有的域和值
返回值:以列表形式返回 hash 中域和域的值,key 不存在,返回空 hash
语法:hdelkey field [field…]
作用:删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略
返回值:成功删除的 field 的数量
语法:hkeys key
作用:查看哈希表 key 中的所有 field 域
返回值:包含所有 field 的列表,key 不存在返回空列表
语法:hvals key
作用:返回哈希表中所有域的值
返回值:包含哈希表所有域值的列表,key 不存在返回空列表
语法:hexists key field
作用:查看哈希表 key 中,给定域 field 是否存在
返回值:如果 field 存在,返回 1,其他返回 0
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
语法:lpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值,从左到右的顺序依次插入到表头
返回值:数字,新列表的长度
例:将 a,b,c 插入到 mylist 列表类型
在 redis-desktop- manager 显示
语法:rpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表尾(最右边),各个 value 值按从左到右的顺序依次插入到表尾
返回值:数字,新列表的长度
例:将 a,b,c 插入到 mylist2 列表类型
在 redis-desktop- manager 显示
语法:lrange key start stop
作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以1表示列表的第二个元素;start,stop 是列表的下标值,也可以是负数的下标,-1 表示列表的最后一个元素,-2 表示列表的倒数第二个元素,以此类推。start ,stop 超出列表的范围不会出现错误。
返回值:指定区间的列表
语法:lindex key index
作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询。0 表示列表的第一个元素,以1表示列表的第二个元素;start,stop 是列表的下标值,也可以是负数的下标,-1 表示列表的最后一个元素,-2 表示列表的倒数第二个元素,以此类推。
返回值:指定下标的元素;index 不在列表范围,返回 nil
语法:llen key
作用:获取列表 key 的长度
返回值:数值,列表的长度;key 不存在返回 0
语法:Irem key count value
作用:根据参数 count 的值,移除列表中与参数 value 相等的元素,count > 0 ,从列表的左侧向右开始移除;couunt < 0从列表的尾部开始移除;count = 0 移除表中所与 value 相等的值
返回值:数值,移除的元素个数
语法:Iset key index value
作用:将列表 key 下标为 index 的元素的值设置为 value。
返回值:设置成功返回 ok;key 不存在或者 index 超出范围返回错误信息
语法:linsert key BEFORE|ALFTER pivot value
作用:将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置。key 不存在,pivot 不在列表中,不执行任何操作
返回值:命令执行成功,返回新列表的长度。没有找到 pivot 返回 -1,key 不存在返回
redis 的 Set 是 string 类型的无序集合,集合成员是唯一的, 即集合中不能出现重复的数据。
语法:sadd key member [member…]
作用:将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略,不会再加入
返回值:加入到集合的新元素的个数。不包括被忽略的元素
语法:smembers key
作用:获取集合 key 中的所有成员元素,不存在的 key 视为空集合
语法:sismember key member
作用:判断 member 元素是否是集合 key 的成员
返回值:member 是集合成员返回 1,其他返回 0
语法:scard key
作用:获取集合里面的元素个数
返回值:数字,key 的元素个数;其他情况返回 0
语法:srem key member [member…]
作用:删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略
返回值:数字,成功删除的元素个数,不包括被忽略的元素
语法:srandmember key [count]
作用:只提供 key, 随机返回集合中一个元素,元素不删除,依然在集合中;提供了 count 时,count 正数,返回包含 count 个数元素的集合,集合元素各不相同。count 是负数,返回一个 count 绝对值的长度的集合,集合中元素可能会重复多次。
返回值:一个元素;多个元素的集合
语法:spop key [count]
作用:随机从集合中删除一个元素,count 是删除的元素个数
返回值:被删除的元素,key 不存在或空集合返回 nil
redis 有序集合 zset 和集合 set 一样也是 string 类型元素的集合,且不允许重复的成员。不同的是 zset 的每个元素都会关联一个分数(分数可以重复),redis 通过分数来为集合中的成员进行从小到大的排序。
语法:zadd key score member [score member…]
作用:将一个或多个 member 元素及其 score 值加入到有序集合key 中,如果 member存在集合中,则更新值;score 可以是整数或浮点数
返回值:数字,新添加的元素个数
例:创建保存学生成绩的集合
在 redis-desktop- manager 显示
语法:zrange key start stop [WITHSCORES]
作用:查询有序集合,指定区间的内的元素。集合成员按 score 值从小到大来排序。start,stop 都是从 0 开始。0 是第一个元素,1 是第二个元素,依次类推。以 -1表示最后一个成员,-2 表示倒数第二个成员。WITHSCORES 选项让 score 和 value 一同返回。
返回值:自定区间的成员集合
例1:显示集合的全部元素,不显示 score,不使用 WITHSCORES
例2:显示集合的全部元素,并使用 WITHSCORES
语法:zrevrange key start stop [WITHSCORES]
作用:返回有序集 key 中, 指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。其它同 zrange 命令。
返回值:自定区间的成员集合
语法:zrem key member [member…]
作用:删除有序集合 key 中的一个或多个成员,不存在的成员被忽略
返回值:被成功删除的成员数量,不包括被忽略的成员
语法:zcard key
作用:获取有序集 key 的元素成员的个数
返回值:key 存在返回集合元素的个数,key 不存在,返回 0
语法:zrangebyscore key min max [WITHSCORES ] [LIMIT offset count]
作用:
返回值:指定区间的集合数据
注意:[LIMIT offset count] 是做分页处理,用法同 mysql 的分页查询一致
例1:查询工资 2000 - 3000 的员工
例2:查询工资 2000 - 4500 的员工(不包含)
例3:查看工资小于 3000 的员工
语法:zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
作用:返回有序集 key 中,score 值介于 max 和 min 之间(默认包括等于 max 或 min)的所有的成员。 有序集成员按 score 值递减(从大到小)的次序排列。其他同zrangebyscore
语法:zcount key min max
作用:返回有序集 key 中,score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max)的成员的数量
事务是指一系列操作步骤,,这一系列的操作步骤,要么完全地执行,要么完全地不执行。
Redis 中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令,redid 事务保证这些命令被执行时中间不会被任何其他操作打断。
语法:multi
作用:标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中
返回值:总是返回 ok
语法:exec
作用:执行所有事务块内的命令
返回值:事务内的所有执行语句内容,事务被打断(影响)返回 nil
语法:discard
作用:取消事务,放弃执行事务块内的所有命令
返回值:总是返回 ok
语法:watch key [key …]
作用:监视一个(或多个)key,如果在事务执行之前这个(或这些)key 被其他命令所改动,那么事务将被打断
返回值:总是返回 ok
语法:unwatch
作用:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后,EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了
返回值:总是返回 ok
事务的执行步骤:首先开启事务,其次向事务队列中加入命令,最后执行事务提交
例:事务的执行
执行事务步骤:
执行步骤:
执行步骤:
Redis的WATCH机制
WATCH机制原理:
WATCh的事例
持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而放在磁盘就算是一种持久化。
Redis 的数据存储在内存中,内存是瞬时的,如果 linux 宕机或重启,又或者 Redis 崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis 提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
什么是RDB方式?
Redis Database(RDB), 就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是 dump.rdb。 RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用。RDB 恢复数据时比其他AOF速度快。
如何实现?
RDB 方式的数据持久化,仅需在 redis.conf 文件中配置即可,默认配置是启用的。
在配置文件 redis.conf 中搜索 SNAPSHOTTING,查找在注释开始和结束之间的关于 RDB 的配置说明。配 SNAPSHOTTING 置地方有三处。
配置执行 RDB 生成快照文件的时间策略
dbfilename:设置 RDB 的文件名,默认文件名为 dump.rdb
dir:指定 RDB 文件的存储位置,默认是 ./ 当前目录
配置步骤:
执行:vim redis.conf,修改文件
总结:
什么是AOF方式
Append-only File(AOF), Redis 每次接收到一条改变数据的命令时,它将把该命令写到一个 AOF 文件中(只记录写操作,读操作不记录),当 Redis 重启时,它通过执行 AOF 文件中所有的命令来恢复数据。
如何实现
AOF方式的数据持久化,仅需在redis.conf 文件中配置即可
配置项:
appendonly:默认是 no,改成 yes 即开启了aof 持久化
appendfilename:指定 AOF 文件名,默认文件名为 appendonly.aof
dir:指定 RDB 和 AOF 文件存放的目录,默认是 ./
appendfsync:配置向 aof 文件写命令数据的策略
auto-aof-rewrite-min-size:允许重写的最小 AOF 文件大小,默认是 64M。当 ao f文件大于 64M时,开始整理 aop 文件, 去掉无用的操作命令。缩小 aop 文件。
配置步骤:
停止运行的 redis,备份要修改的 redis.conf 文件
查看 redis 安装目录 /src 下有无 .aof 文件。默认是在 redis 的当前目录
编辑 redis.conf
通过持久化功能,Redis 保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,那该怎么实现呢?Redis 的主从复制。
Redis 提供了复制(replication)功能来自动实现多台 redis 服务器的数据同步。
我们可以通过部署多台 redis, 并在配置文件中指定这几台 redis 之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即 master/slave,并且 redis 默认 master 用于写,slave 用于读,向 slave 写数据会导致错误。
方式1 的实现步骤:
模拟多 Reids 服务器,在一台已经安装 Redis 的机器上,运行多个 Redis 应用模拟多个 Reids 服务器。一个 Master,两个 Slave。
新建三个 Redis 的配置文件
编辑 Master 配置文件
编辑 Master 的配置文件 redis6380.conf:在空文件加入如下内容
include /usr/local/redis-6.0.5/redis.conf
daemonize yes
port 6380
pidfile /var/run/redis_6380.pid
logfile 6380.log
dbfilename dump6380.rdb
编辑 Slave 配置文件
编辑 Slave 的配置文件 redis6382.conf 和 redis6384.conf:在空文件加入如下内容
include /usr/local/redis-6.0.5/redis.conf
daemonize yes
port 6382
pidfile /var/run/redis_6382.pid
logfile 6382.log
dbfilename dump6382.rdb
slaveof 127.0.0.1 6380
启动服务器 Master/Slave 都启动
当 Master 服务出现故障,需手动将 slave 中的一个提升为 master,剩下的 slave 挂至新的 master 上(冷处理:机器挂掉了,再处理)
命令:
执行步骤:
原来的服务器重新添加到主从结构中
Sentinel 哨兵是 redis 官方提供的高可用方案,可以用它来监控多个 Redis 服务实例的运行情况。Redis Sentinel 是一个运行在特殊模式下的 Redis 服务器。Redis Sentinel 是在多个 Sentinel 进程环境下互相协作工作的。
Sentinel 系统有三个主要任务:
Sentinel 配置文件
修改 port 26380、port26382、port26384
修改 sentinel monitor mymaster 127.0.0.1 6380 2
格式:
sentinel monitor
Sentinel 监控主(Master)Redis,Sentinel 根据 Master 的配置自动发现 Master 的 Slave,Sentinel 默认端口号为 26379。
sentinel26380.conf
sentinel26382.conf、sentinel26384.conf的修改同上一致
redis 安装时 make 编译后就产生了 redis-sentinel 程序文件,可以在一个 redis 中运行多个 sentinel 进程。
执行以下三条命令,将创建三个监视主服务器的 Sentinel 实例:
让 Master 的 Redis 停止服务,执行 shutdown。
先执行 info replication 确认 Master 的 Redis,再执行 shutdown
当 Master 的 Redis 停止服务后,Sentinel 会自动进行选举,随机从剩下的两个从服务器选出一个成为新的 Master 。
查看主服务器6380端口的信息:
Sentinel 会自行进行监视,把修复好的 redis 添加到主服务器中。
查看主服务器6380端口的信息:
访问 Redis 默认是没有密码的,这样不安全,任意用户都可以访问。可以启用使用密码才能访问 Redis。设置 Redis 的访问密码,修改 redis.conf 中这行 requirepass 密码。密码要比较复杂,不容易破解,而且需要定期修改。因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,需要指定非常非常强大的密码来防止暴力破解。
修改 redis.conf,使用 vim 命令。找到 requirepass 行去掉注释,requirepass 空格后就是密码。
例:设置访问密码是 123456,这是练习使用,生产环境要设置复杂密码
修改 redis.conf 文件,把 # bind 127.0.0.1 前面的注释 # 号去掉,然后把 127.0.0.1 改成允许访问你 redis 服务器的 ip 地址,表示只允许该 ip 进行访问。多个 ip 使用空格分隔。
例如:bind 192.168.1.100 192.168.2.10
修改 redis 的端口,这一点很重要,使用默认的端口很危险,redis.conf 中修改 port 6379,将其修改为自己指定的端口(可随意),端口 1024 是保留给操作系统使用的。用户可以使用的范围是 1024-65535。
使用 -p 参数指定端口,例如:./redis-cli -p 新设置端口
使用 Redis 官方推荐的 Jedis,在 java 应用中操作 Redis。Jedis 几乎涵盖了 Redis 的所有命令。操作 Redis 的命令在 Jedis 中以方法的形式出现。jedis 完全兼容 redis 2.8.x and 3.x.x
浏览器打开:https://mvnrepository.com/artifact/redis.clients/jedis
浏览器打开:https://mvnrepository.com/artifact/org.apache.commons/commons-pool2
package cn.edu.huat.redis;
import redis.clients.jedis.Jedis;
import java.util.List;
public class RedisString {
public static void main(String[] args) {
/**
* 通过网络,访问Redis服务器:
* 1.修改redis .conf ,启动redis需要指定redis . conf的位置
* 2.关闭linux防火墙,或者让redis的端口通过防火墙。
*/
//创建Jedis对象,指定连接的redis服务器的ip,端口
/**
* String host: redis所在的linux服务器的ip
* int port: redis运行的端口号
*/
String host = "192.168.238.129";
int port = 6379;
Jedis jedis = new Jedis(host,port);
//设置访问密码
jedis.auth("123456");
//调用Jedis对象的方法,操作redis数据
jedis.set("break","热干面");
//获取key的值
String value = jedis.get("break");
System.out.println("break key = " + value);
//mset一次创建多个key-value
jedis.mset("lunch","猪排盖饭","dinner","牛排");
List<String> values = jedis.mget("break","lunch","dinner");
for (String val : values){
System.out.println(val);
}
}
}
package cn.edu.huat.redis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisUtils {
private static JedisPool pool;
//创建JedisPool对象
public static JedisPool open(String ip,int port){
if (pool == null){
//创建JedisPool
JedisPoolConfig config = new JedisPoolConfig();
//给config设置连接池的参数
//设置最大的连接数,一个线程就是一个Jedis
config.setMaxTotal(20);
//设置最大的空闲数
config.setMaxIdle(2);
//设置检查项为true,表示从线程池中获取的对象一定是经过检查可用的
config.setTestOnBorrow(true);
//使用config对象创建JedisPool
/**
* poolConfig:配置器JedisPoolConfig
* host: redis所在的linux的ip
* port: redis的端口
* timeout :连接redis的超时,毫秒值
* password: redis的访问密码
*/
pool = new JedisPool(config,ip,port,6000,"123456");
}
return pool;
}
//关闭Pool对象
public static void close(){
if (pool != null){
pool.close();
}
}
}
package cn.edu.huat.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.List;
public class RedisStringPool {
public static void main(String[] args) {
/**
* 通过网络,访问Redis服务器:
* 1.修改redis .conf ,启动redis需要指定redis . conf的位置
* 2.关闭linux防火墙,或者让redis的端口通过防火墙。
*/
//创建Jedis对象,指定连接的redis服务器的ip,端口
/**
* String host: redis所在的linux服务器的ip
* int port: redis运行的端口号
*/
String host = "192.168.238.129";
int port = 6379;
//创建JedisPool对象,从JedisPool中获取Jedis
JedisPool pool = null;
Jedis jedis = null;
try {
pool = RedisUtils.open(host,port);
//从pool中获取Jedis
jedis = pool.getResource();
//调用Jedis对象的方法,操作redis数据
jedis.set("break","热干面2");
//获取key的值
String value = jedis.get("break");
System.out.println("break key = " + value);
jedis.mset("lunch","猪排盖饭2","dinner","牛排2");
List<String> values = jedis.mget("break","lunch","dinner");
for (String val : values){
System.out.println(val);
}
} finally {
//关闭Jedsi对象,把从pool中获取的Jedis放回到Pool,供其他对象使用
if (jedis != null){
jedis.close();
}
}
}
}