文章目录
第一章 什么是redis
redis的特点
- redis是一个非关系型数据库,基于C语言开发;
- 数据结构为 key-value 形式,不支持SQL语句,支持五种数据类型:strings 、list 、hash 、set、zset,三种特殊类型:位图(bitmap)、HyperLoglog、GEO(英文全称 geographic);
- 支持各种语言类型的api,如 Java,C/C++,C#,Python,Ruby 等;
- 基于内存存储(活动范围在内存中),读写速度快;
- 支持数据持久化,可以对数据进行永久保存;
- 操作属于原子性,使用单线程+io多路复用方式,单线程避免了线程的上下文切换。
第二章 redis安装
2.1 window系统安装
下载地址:https://github.com/tporadowski/redis/releases
可以选择自己想要的文件类型下载,
1 第一个是一个安装包
2 是一个压缩包
3 其他的是源代码
下载成功之后,直接安装,运行即可,window自带的有c语言环境。
安装目录文件如下:
点击 redis-server.exe 运行,服务开启
运行成功如下
点击 redis-cli.exe 运行客户端,成功如下
提示
1 如果关闭了运行服务器的窗口,则服务就关闭了,可以把redis注册到window的服务中。
2 点击redis-server.exe 后面不跟配置文件,则选择默认的配置文件,如果要选择对应的配置文件,则在cmd 命令窗口中,选择对应的配置文件。
指定配置文件
2.2 Linux系统安装
下载
[root@centos ~]# yum -y install gcc gcc-c++
[root@centos ~]# wget http://download.redis.io/releases/redis-5.0.9.tar.gz
[root@centos ~]# tar -zxvf redis-5.0.9.tar.gz
[root@centos~]# cd redis-5.0.9
[root@centos redis-5.0.9]# make
[root@centos redis-5.0.9]# make PREFIX=/usr/local/redis install
[root@centos redis-5.0.9]# cp redis.conf /usr/local/redis
启动服务器
[root@centos redis-5.0.9]# cd /usr/local/redis
[root@centos redis]# vim redis.conf
#找到这个修改为yes,表示Redis启动的时候采用后台模式
daemonize yes
[root@centos redis]# ./bin/redis-server redis.conf
启动客户端
[root@centos redis]# ./bin/redis-cli
文件介绍
redis-server :Redis服务器
redis-cli :Redis客户端
redis-sentinel :Redis哨兵端
redis-benchmark:Redis性能测试工具
redis-check-aof :AOF文件修复工具
redis-check-rdb :RDB文件检索工具
2.3 可视化工具安装
Redis 存在许多第三方可视化工具,可以让您更加直观形象地的操作 Redis 数据库,常见的 Redis GUI 工具有 Redis Desktop Manager(又称 RDM)、Another Redis DeskTop Manager 及 FastoRedis。
第三章 配置文件
配置文件名称 redis.config
3.1 客户端命令的形式修改
在客户端输入
获取配置:config get *
获取所有的配置
修改配置:redis 127.0.0.1:6379> CONFIG SET 配置项名称 配置项参数值
提示
在客户端修改的配置项,如果服务重启,则配置失效。
3.2 在配置文件中修改
配置项说明
提示
在配置文件中修改的配置项,永久有效。
配置文件中的代码是所有的配置案例,可以复制翻译查看该配置的意思
第四章 数据类型
Redis 是 Key-Value 类型缓存型数据库,Redis 为了存储不同类型的数据,提供了五种常用数据类型,如下所示:
- string(字符串)
- hash(哈希散列)
- list(列表)
- set(集合)
- zset(sorted set:有序集合)
4.1 key键
您可以把 key 看成 value 的变量,通过检索 key 就可以找到对应的 value 值。
key 的类型
key 的命名规范
key 的过期时间
key的类型
key的类型对应着value的类型,五种(string、list、hash、set、zset);如果value的类型是string ,则key的类型是strings,如果是list,则key是list。
key的命名规范
key 的命名需要遵循以下规则:
key 取值不可以太长,否则会影响 value 的查找效率,并且浪费内存空间。
key 取值也不能过短,否则会使得 key 可读性变差。
uesr:id:01:username
使用:
来分隔key,可以达到分组的效果,如下所示
key: user:uv:20221001
key : user:uv:20221002
key的过期策略
Redis 允许你为 key 设置一个过期时间(使用 EXPIRE 等命令),也就是“到点自动删除”,,避免使用频率不高的 key 长期存在,从而占用内存资源;二是控制缓存的失效时间。
key的命令
提示
如果对一个已经存在的key进行赋值,则会把原来的值给覆盖掉,如果要修改一个值,即可以这样设置,如果需要删除,则直接删除即可。
4.2 string字符串
string使用c语言编写,string在c语言的结构定义为
struct sdshdr{
//记录buf数组中已使用字符的数量,等于 SDS 保存字符串的长度
int len;
//记录 buf 数组中未使用的字符数量
int free;
//字符数组,用于保存字符串
char buf[];
127.0.0.1:6379> SET key value [EX seconds|PX milliseconds] [NX|XX]
其中[]内代表可选参数,其含义如下所示:
EX seconds:设置指定的过期时间,以秒为单位;
PX milliseconds:设置指定的过期时间,以毫秒为单位;
NX:先判断 key 是否存在,如果 key 不存在,则设置 key 与 value;
XX:先判断 key 是否存在,如果 key 存在,则重新设置 value。
Redis字符串命令
4.3 list列表
Redis list(列表)相当于 Java 语言中的 LinkedList 结构,是一个链表而非数组,其插入、删除元素的时间复杂度为 O(1),但是查询速度欠佳,时间复杂度为 O(n)。
Redis 列表可以被当做栈、队列来使用,如果列表的元素是“左进右出”那就是队列模型;如果元素是“右进右出”那就是栈模型。
常用命令
4.4 hash类型
Redis hash(哈希散列)是由字符类型的 field(字段)和 value 组成的哈希映射表结构(也称散列表),它非常类似于表格结构。在 hash 类型中,field 与 value 一一对应,且不允许重复。
结构:key filed value
常用命令
4.5 set类型
Redis set (集合)遵循无序排列的规则,集合中的每一个成员(也就是元素,叫法不同而已)都是字符串类型,并且不可重复。Redis set 是通过哈希映射表实现的,所以它的添加、删除、查找操作的时间复杂度为 O(1)。集合中最多可容纳 2^32 - 1 个成员(40 多亿个)。
常用命令
4.6 zset类型
Redis zset(有序集合)中的成员是有序排列的,它和 set 集合的相同之处在于,集合中的每一个成员都是字符串类型,并且不允许重复;而它们最大区别是,有序集合是有序的,set 是无序的,这是因为有序集合中每个成员都会关联一个 double(双精度浮点数)类型的 score (分数值),Redis 正是通过 score 实现了对集合成员的排序。
常用命令
4.7 位图(bitmap)
位图的本质是操作0和1,也就是bool类型的真与假,如: 统计一年365天一个用户的登录情况。登录了就设置为1,没有登录就设置为0。通过0和1就能解决问题,如果用普通的结构,则占用空间非常大。
位图的操作的数据配置上还是字符串,也就是byte数组。
案例演示 :
把一个字符串转换为二进制,然后使用位图操作二进制数获取字符串。
获取he
的二进制数
>>> bin(ord("h"))
'0b1101000'
>>> bin(ord("e"))
'0b1100101'
对两个字符串的二进制数进行拼接
把 h 和 e 的二进制码连接在一起,第一位的下标是 0,依次递增至 15,然后将数字为 1 的位置标记出来,得到 1/2/4/9/10/13/15,我们把这组数字称为位的“偏置数”,最后按照上述偏置数对字符 a 进行如下位图操作。**注意,key 的初始二进制位全部为 0。**
接下来操作二进制数
127.0.0.1:6379> setbit a 1 1
(integer) 1
127.0.0.1:6379> setbit a 2 1
(integer) 0
127.0.0.1:6379> setbit a 4 1
(integer) 0
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> get a
"h"
127.0.0.1:6379> setbit a 9 1
(integer) 0
127.0.0.1:6379> setbit a 10 1
(integer) 0
127.0.0.1:6379> setbit a 13 1
(integer) 0
127.0.0.1:6379> setbit a 15 1
(integer) 0
127.0.0.1:6379> get a
"he"
127.0.0.1:6379> getbit a 1
(integer) 1
127.0.0.1:6379> getbit a 4
(integer) 1
127.0.0.1:6379> getbit a 5
(integer) 0
常用命令
- SETBIT命令
用来设置或者清除某一位上的值,其返回值是原来位上存储的值。key 在初始状态下所有的位都为 0 ,语法格式如下:SETBIT key offset value - GETBIT命令
用来获取某一位上的值。示例如下:GETBIT user:1 0 - BITCOUNT命令
统计指定位区间上,值为 1 的个数。语法格式如下:BITCOUNT key [start end]
4.8 HyperLoglog
它非常适用于海量数据的计算、统计,其特点是占用空间小,计算速度快。
基数定义
基数定义:一个集合中不重复的元素个数就表示该集合的基数,比如集合 {1,2,3,1,2} ,它的基数集合为 {1,2,3} ,所以基数为 3。
HyperLoglog 不会储存元素值本身,HyperLoglog 只记录元素的数量。
常用命令
4.9 GEO地理位置
geo用于获取两个位置的信息,前提是要先把位置的经纬度信息录入到系统中。
常用命令
- GEOADD 命令
GEOADD key longitude latitude member [longitude latitude member …]
longitude:位置地点所处的经度;
latitude:位置地点所处的纬度;
member:位置名称。
将给定的经纬度的位置名称(纬度、经度、名字)与 key 相对应,这些数据以有序集合的形式进行储存。
GEOADD命令以标准的x,y形式接受参数, 所以用户必须先输入经度,然后再输入纬度。GEOADD命令能够记录的坐标数量是有限的,如果位置非常接近两极(南极/北极)区域,那么将无法被索引到。因此当您输入经纬度时,需要注意以下规则:
有效的经度介于 -180 度至 180 度之间。
有效的纬度介于 -85.05112878 度至 85.05112878 度之间。
4.10 数值操作命令
-
INCR命令
INCR 命令指对 value 数值做加 1 操作,其数值范围是 64 位的有符号整型(-9223372036854775808 至 9223372036854775807)。 -
DECR命令
该命令与 INCR 命令相反,它对数值执行减 1 操作。 -
INCRBY命令
INCRBY key increment
127.0.0.1:6379> INCRBY fans:num 3 -
DECRBY命令
该命名与 INCRBY 命令相反,它表示在原数值的基础上进行指定数值的自减运算。
INCRBY key decrement -
INCRBYFLOAT
该命令是 string 中唯一操作浮点数的命令,浮点数可以为正数或者负数,从而实现对数值的加减操作。
第五章 事务
Redis一个事务从开始到执行会经历以下三个阶段:
开始事务:MULTI
命令入队
执行事务:EXEC
5.3、Redis事务的常见命令
MULTI
Multi命令用于标记一个事务块的开始。事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由EXEC命令原子性(atomic)地执行。
返回值:总是返回OK。
EXEC
Exec命令用于执行所有事务块内的所有命令。
返回值:事务块内所有命令的返回值,按命令执行的先后顺序排列,当操作被打断时,返回空值nil 。
DISCARD
Discard命令用于放弃执行事务块内的所有命令。
返回值:总是返回OK 。
WATCH
Watch命令用于监视一个(或多个) key,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
UNWATCH
Unwatch命令用于取消 WATCH 命令对所有key的监视。
第六章 数据持久化
Redis 提供了两种持久化机制:第一种是 RDB,又称快照(snapshot)模式,第二种是 AOF 日志,也就追加模式。
Redis数据持久化机制
RDB持久化:该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘。
AOF持久化:该机制将以日志的形式记录服务器所处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。
同时应用RDB和AOF:同时配置这两种方式即可。
无持久化:可通过配置的方式禁用Redis服务器的持久化功能,这样我们就可以将Redis视为一个功能加强版的memcached了。
5.1 RDB持久化
手动持久化
手动触发是通过SAVAE命令或者BGSAVE命令将内存数据保存到磁盘文件中。
自动持久化
RDB快照存储方式:缺省情况下,Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开redis.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1:#在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10:#在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000:#在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
注意:关于dump.rdb文件存储的位置,它是设置是在redis.conf文件中,dir ./,代表了服务器启动时的当前路径。
5.2 AOF持久化
AOF日志文件方式:AOF是append only file的缩写,它默认是关闭的,需要在redis.conf中打开,将appendonly no改为appendonly yes,在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always:#每次有数据修改发生时都会写入AOF文件。
appendfsync everysec:#每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no:#从不同步,高效但是数据不会被持久化。
aof持久化机制
Redis 在收到客户端修改命令后,先进行相应的校验,如果没问题,就立即将该命令存追加到 .aof 文件中,也就是先存到磁盘中,然后服务器再执行命令。
2) 重写机制
Redis 在长期运行的过程中,aof 文件会越变越长。如果机器宕机重启,“重演”整个 aof 文件会非常耗时,导致长时间 Redis 无法对外提供服务。因此就需要对 aof 文件做一下“瘦身”运动。
重写机制对比
5.3 AOF和RDB对比
第七章 redis主流配置
第一阶段:单机版本
优点:部署简单,使用方便
缺点:采用单个Redis节点部署架构,没有备用节点实时同步数据,不提供备份策略,容灾性较差
第二阶段:主从复制
优点: 主从模型可以提高读的能力,在一定程度上缓解了写的能力,实现了读写分离
缺点:主节点宕机了,整个集群就没有可写的节点了
第三阶段:哨兵模式
优点:哨兵模式可以提高读的能力,在一定程度上缓解了写的能力,并且主机故障确实能实现自动故障切换,提供稳定的服务
缺点:仍然只有一个主节点,当并发写请求较大时,哨兵模式并不能缓解写压力
第四阶段:高可用集群
优点:通过高可用集群,解决了写操作无法负载均衡以及存储能力受到单机限制的问题,实现了较为完善的高可用方案
缺点:在select命令页有提到,集群模式下只能使用一个库,虽然平时一般也是这么用的,但是要了解一下
第八章 Jedis连接redis
Jedis相当于jdbc连接数据库的工具,也需要创建连接关闭连接,也需要连接池。
常见错误:
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
可能原因一:Redis的配置文件中没有注释掉bind 127.0.0.1
可能原因二:Linux的防火墙没有关闭,或者把redis的端口都放开。
可能原因三:代码中的IP地址和端口写错了,请仔细检查一下!
redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required.
可能原因一:出现这个说明Redis登录需要密码,而你的代码文件中并没有指明密码是多少,Redis登录是否启用密码请在配置文件中配置requirepass
1 引入依赖。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
2 创建测试案例
@Test
public void test(){
Jedis jedis = new Jedis("192.168.10.38",6379);
jedis.auth("123456");
String name = jedis.get("name");
System.out.println(name);
jedis.set("username","pengyuqing");
String username = jedis.get("username");
System.out.println(username);
jedis.close();
}
主从版连接
@Test
public void testLink() {
// 创建对应连接
Jedis jedis_M = new Jedis("192.168.10.38", 8001);
jedis_M.auth("123456");// 设置密码
Jedis jedis_S1 = new Jedis("192.168.10.38", 8002);
jedis_S1.auth("123456");// 设置密码
Jedis jedis_S2 = new Jedis("192.168.10.38", 8003);
jedis_S2.auth("123456");// 设置密码
// 从机连接主机
//jedis_S1.slaveof("192.168.10.38", 8001);
// jedis_S2.slaveof("192.168.10.38", 8001);
// 主机写入数据
jedis_S2.set("username", "zhangsan");
// 从机读取数据
System.out.println(jedis_S1.get("username"));
System.out.println(jedis_S2.get("username"));
// 释放所有资源
jedis_S2.close();
jedis_S1.close();
jedis_M.close();
}