目录
1.redis介绍
2.redis常用命令(可以在官网的命令中查看redis的所有命令)
2.1终端命令
2.2 redis通用命令
2.3五大基本类型的命令以及特殊情况分析 (导航)
3.事务
4. redis实现消息订阅
5. redis的两种持久化策略
5.1 rdb策略
5.2 aof策略
1.redis介绍
redis即远程字典服务,是当下最热门的NoSQL(非关系型数据库)技术之一,采用KV键值对的数据结构存储数据,也被称之为结构化数据库。Redis会周期性地将更新的数据写入磁盘并将更新操作写入追加的记录文件,并在此基础上实现了主从同步。Redis是基于内存存储的,能够实现持久化,并且效率高,支持多种语言和多种数据类型,同时也支持集群、事务等。
redis支持五种基本数据类型String、Set、Zset、Hash、List以及三种特殊类型Bitmaps、HyperLogLog、Geospatial。
redis之所以速度快是因为采用C语言编写的,基于内存操作且是单线程的,相较于多线程而言省去了上下文切换的过程,这个过程是非常耗时的。由于redis基于内存操作,所以CPU不是redis的瓶颈,机器的内存和网络带宽才是。
2.redis常用命令(可以在官网的命令中查看redis的所有命令)
2.1终端命令
- redis-server redis.conf
使用redis.conf配置文件打开服务器,需要在redis.conf目录下执行,在其他目录下开启服务器需要使用相对路径或绝对路径。也可以使用自己配置的redis的配置文件。
- redis-cli -p 6379
与服务器建立连接,6379为redis的默认端口号。
- ps -ef|grep redis
查看redis的进程是否开启,如果开启了redis就能够看到redis的进程。
- redis-benchmark
用于redis的压力测试,以下是压力测试可能用到的一些参数:
例:使用本机进行压力测试,采用2个并发连接,每个连接进行2次请求:
2.2 redis通用命令
先加入数据方便演示:
- keys *
获取所有的key。
- keys key
获取指定的key,可用来查看是否存在指定键值对;或者使用exists key查看是否存在。
- shutdown
关闭服务器。
- exit
退出到终端。
- select 编号
切换数据库,可以在不同数据库存储不同的信息进行分类;默认有16个数据库,编号从0开始。
- dbsize
查看当前数据库存储的信息数量。
- flushdb
清空当前数据库中的所有信息。
- flushall
清空所有数据库中的所有信息。
- move key 序号
将指定键值对信息移到指定序号的数据库中。
- del key
删除指定键值对,当删除多个键值对时可以在del后面加上多个key,每个key之间用空格分开。
- expire key time
设置指定键值对的过期时间,单位为秒,过期后该键值对就会消失。
- ttl key
查看指定键值对还有多长时间过期,单位为秒,当返回-1时代表没有设置过期时间,当返回-2时代表已经过期。
- type key
查看key对应的value的类型。
- watch key1 key2 ...
用于事务中,监视某些对象是否在入队后进行了修改,如果在exec命令执行前未进行修改说明监视成功,如果有其他客户端进行了修改,那么表示监视失败,并且在执行exec命令后事务中的所有命令不会被执行;无论是否监视成功,事务在执行exec或者discard命令后监视器自动失效。(比如对name进行监视,在客户端1有一个事务,包含了get命令,但是在执行exec之前另一客户端修改了name的值并成功执行,此时就会监测到name的值被修改,那么在执行exec命令后事务不会去执行)可以使用unwatch命令手动解除所有的监视器。(会在事务章节演示)
2.3五大基本类型的命令以及特殊情况分析 (导航)
- String类型
redis学习-String类型的命令介绍以及特殊情况分析-CSDN博客
- List类型
redis学习-List类型相关命令以及特殊情况分析-CSDN博客
- Set类型
redis学习-Set集合类型相关命令及特殊情况分析-CSDN博客
- Zset类型
redis学习-Zset集合类型相关命令及特殊情况分析-CSDN博客
- Hash类型
redis学习-Hash类型相关命令及特殊情况分析-CSDN博客
3.事务
- redis的事务是不保证原子性的,但单条命令的执行是保证原子性的,当一个事务中的一个命令执行失败时其他命令依旧能够执行;redis事务的本质是一组命令的集合,会将一个事务中所有命令序列化,按照顺序依次执行,这也保证了执行命令时不受干扰,所以redis的事务在执行命令时具有依次性、顺序性、排他性。
- redis的事务没有隔离级别的概念,命令一开始只是放在事务中,并没有被执行,只有当发起EXEC执行命令时才会执行。因为一开始就没有执行,不执行就不存在“事务内的查询要看到事务的更新但事务外的查询不能看到”这种问题。
- redis命令包含三部分:开启事务(multi)、命令入队(要执行的命令,比如set、get等)、执行事务(exec)。除此之外,还有一个取消事务的命令discard,可以在开启事务但未执行事务时使用,执行取消事务时会立即退出事务,且所有的命令均不会被执行。
- redis事务在执行时有两种异常,一种是命令使用错误,一种是逻辑错误,当事务发现有的命令不符合规范时(比如使用set时多加了一个字母或者多加了一个参数)会直接报错,所有的命令也就都跟着不会执行;当事务只发现命令在使用时出现了逻辑错误(比如zrange的区间不规范时),则仅在执行该条命令时报错,其他命令则会正常执行。
注意区别报错和执行失败,执行失败不一定会报错,比如有的指令执行失败会返回0,或者返回 (empty array) ," ",nil 等,报错则是会出现提示信息 “(error) ERR 错误信息” 。
- 悲观锁和乐观锁
悲观锁:认为任何时候都会出现问题,无论做什么都要加锁,syncronized就是典型的悲观锁。
乐观锁:认为不会出现问题,不用加锁,只需要每次更新时先检查这期间是否有其他人也更新了,比如CAS机制;在redis中会通过watch监视器来监控更新情况。
watch工作演示:
与此同时,客户端2也开启了事务,包含了一个set,要对k1进行修改,并且事务成功执行:
此时客户端再执行事务,会发现get的结果为nil,表示事务执行失败:
这就是watch监视器起到了作用,在客户端1开启事务后对某些信息进行操作时,如果在此期间有其他客户端对这些信息成功做了修改并且这些信息都被watch监视器监视,那么此次对这些信息的操作就会无效,需要重新执行事务。由于watch监视器只能监视一次,所以再次开启事务时需要重新添加watch监视器。
4. Jedis
Jedis是使用java操作redis的中间件。导入Jedis工具包之后,通过代码
Jedis jedis=new jedis("服务器ip","6379") 创建Jedis对象,随后调用api即可,所有的api和linux的命令相同。
要注意的是,默认情况下redis只允许本地访问,从其他集成开发工具中远程访问redis需要修改配置文件redis.conf,并重新启动服务器。
通过vim redis.conf命令打开配置文件,然后做如下修改:
如果使用的xshell还需要设置防火墙:
firewall-cmd --zone=public --add-port=6379/tcp --permanent
然后重新启动防火墙:
systemctl restarta firewalld.service
这就可以使用Jedis远程操作redis了:
public class TestPing {
public static void main(String[] args) {
//连接redis
Jedis jedis=new Jedis("59.110.8.199",6379);
//测试是否成功连接
System.out.println(jedis.ping());
//使用JSON存储键值对
JSONObject jsonObject=new JSONObject();
JSONObject jsonObject1=new JSONObject();
jsonObject.put("name","abc");
jsonObject1.put("age","11");
//事务的正确用法:更新操作使用multi,并使用try-catch当事务执行出现异常时取消事务的执行;查询操作使用jedis
//使用watch监视器
jedis.watch("name","age");
//开启事务
Transaction multi = jedis.multi();
try{
//事务中的操作使用multi对象的api
multi.set("name",jsonObject.toString());
multi.set("age",jsonObject1.toString());
multi.exec();
}catch (Exception e){
multi.discard();
e.printStackTrace();
}finally {
System.out.println(jedis.get("name"));
System.out.println(jedis.get("age"));
}
}
}
运行结果:
4. redis实现消息订阅
- subscribe 频道名1 频道名2 ...
用来订阅指定的频道,当发布者在这些频道发布消息时订阅者会自动收到。
- unsubscribe 频道名1 频道名2 ...
退订指定的频道,退订后就不会接收到这些频道的消息了。
- publish 频道名 消息
发布者在指定频道中发布消息。
演示:
订阅c1频道,准备接收消息:
发布者在c1频道发送消息:
此时接收方便会收到消息:
当接收方退订c1频道时,将不会收到c1频道的消息:
5. redis的两种持久化策略
5.1 rdb策略
当触发持久化时,redis会fork一个子进程来进行持久化,这个子进程会先将数据写入一个临时的rdb文件中,也就是一个快照,写完后再将这个快照文件直接替换掉之前的rdb文件,并且在这个过程中父进程完全不用参与,可以处理其他请求,从而在更新保存的数据的同时又拥有极高的性能;当进行数据恢复时redis会将快照文件直接读到内存中。当更新频率达到配置文件中save设置的频率,或者执行flushall命令,或者退出redis时会自动触发rdb持久化操作。rdb的优点是适用于大量数据的恢复或者对数据完整性要求不高的恢复;缺点是需要一定的时间间隔触发持久化,这会导致宕机前的最后一次修改会丢失,并且fork子进程会占用一定的内存空间。
以上是配置文件中默认的rdb的save标准,当发生这三种情况时自动更新快照文件:
- 当一小时内发生了至少1次修改操作时
- 当五分钟内发生了至少100次修改操作时
- 当60秒内发生了至少10000次修改操作时
配置文件中还可以配置rdb快照的文件名以及快照放置的文件夹:
在实际应用中,可能需要对rdb文件进行备份,以防丢失;rdb使用默认配置即可。
5.2 aof策略
这个策略会将所有的更新操作记录到日志文件中,当然也是父进程fork的子进程去进行持久化操作,由于读操作不会影响数据,所以不会记录。在记录更新操作时只允许追加文件,不允许修改文件;当需要进行数据恢复时,redis会将日志文件中记录的所有更新操作依次重新执行一次。优点是可以在配置文件中修改aof的执行频率来保持数据的完整性或者提高效率,缺点就是aof文件要比rdb文件大很多,占用较多的空间,并且aof的效率也要比rdb慢,所以默认使用rdb策略的持久化。