Redis
Redis笔记简记
Remote Dictionary Server(Redis)是一个开源的使用 C 语言编写、支持网络、可基于内存
亦可持久化的 Key-Value数据库. Key 字符类型,其值(value)可以是字符串(String), 哈希(Map),
列表(list), 集合(sets) 和有序集合(sorted sets)等类型,每种数据类型有自己的专属命令。所
以它通常也被称为数据结构服务器。
Redis是一个key-value结构的数据库,把redis看做是一个大的Map
Redis的作用:
1.Redis是一个数据库,存储数据,可以对数据执行crud
2.Redis可以作为Cache(缓存)使用,提供数据的查询的性能。
Redis作为缓存应该存储用户经常访问的数据。Redis主要提升的是查询的性能(select)
3.作为分布式锁
Cache(缓存):存在内存中的数据
user发起请求----控制器----Service----Dao---数据库
使用Cache
user发起请求----控制器----Service----Redis
user发起请求----控制器----Service---Redis(没有数据)
---Dao---数据库
1、Redis简介:
Redis是一种数据库。能够存储数据、管理数据的一种软件。
2、数据库应用的发展历程:
单机数据库时代:一个应用,一个数据库实例
缓存、水平切分时代:
读写分离时代:
分表分库时代(集群):
关系型数据库:oracle、mysql、DB2、sqlserver、....
非关系型数据库(NoSql): 彻底改变底层存储机制。不再采用关系数据模型,而是采用聚合数据结构存储数据。
redis、mongoDB、HBase、....
3、Nosql数据模型:
关系型数据库:表
tbl_student tbl_clazz
id name age clazz_id id name
1001 zhangsan 20 111 111 clazz1
1002 lisi 21 111 222 clazz2
非关系型数据库:聚合模型---把一组相关联的数据作为一个整体进行存储和管理。
BSON:数据保存到键值对中、数据和数据之间用逗号隔开,{}表示对象,[]表示数组。
{
id:1001,
name:zhangsan,
age:20,
clazz:{
id:111,
name:clazz1
}
}
{
id:1002,
name:lisi,
age:21,
clazz:{
id:111,
name:clazz1
}
}
K-V键值对、列簇、图表模型等。
Redis采用的是K-V模型存储数据的。
4、Redis是一个用C语言编写的、开源的、基于内存运行并支持持久化的、高性能的NoSQL数据库.也是当前热门的NoSQL数据库之一。
Redis中的数据大部分时间都是存储内存中的,适合存储频繁访问、数据量比较小的数据。
缓存数据库
5、安装redis:参考安装手册。
下载:
解压:tar -zxvf ...
编译:make
需要先安装gcc
编译结果:在redis的安装目录下src目录中,生成redis的一系列可执行文件。
安装:make install
把redis的安装目录下src目录中生成redis的一系列可执行文件拷贝到/usr/local/bin中,
在任何目录下都可以执行redis命令。
6、启动redis服务:
1)前台启动:在任何目录下执行 redis-server
2)后台启动:在任何目录下执行 redis-server &
3)启动redis服务时,指定配置文件:redis-server redis.conf &
7、关闭redis服务:
1)、通过kill命令:
ps -ef|grep redis查看pid
kill -9 pid
2)、通过redis-cli命令关闭:
redis-cli shutdown
8、redis的客户端:用来连接redis服务,向redis服务端发送命令,并且显示redis服务处理结果。
redis-cli:是redis自带客户端,使用命令redis-cli就可以启动redis的客户端程序。
./mysql -uroot -p
redis-cli:默认连接127.0.0.1(本机)的6379端口上的redis服务。
redis-cli -p 端口号:连接127.0.0.1(本机)的指定端口上的redis服务。
redis-cli -h ip地址 -p 端口:连接指定ip主机上的指定端口的redis服务。
9、退出客户端:在客户端执行命令:exit或者quit
10、redis的基本知识:
1)、测试redis服务的性能:
redis-benchmark
2)、查看redis服务是否正常运行:
ping 如果正常---pong
3)、查看redis服务器的统计信息:
info 查看redis服务的所有统计信息
info [信息段] 查看redis服务器的指定的统计信息,如:info Replication
4)、redis的数据库实例:作用类似于mysql的数据库实例,redis中的数据库实例只能由redis服务来创建和维护,
开发人员不能修改和自行创建数据库实例;默认情况下,redis会自动创建16个数据库实例,
并且给这些数据库实例进行编号,从0开始,一直到15,使用时通过编号来使用数据库;可以通过配置文件,
指定redis自动创建的数据库个数;redis的每一个数据库实例本身占用的存储空间是很少的,所以也不造成存储空间的太多浪费。
默认情况下,redis客户端连接的是编号是0的数据库实例;可以使用select index切换数据库实例。
5)、查看当前数据库实例中所有key的数量:dbsize
6)、查看当前数据库实例中所有的key:keys *
7)、清空数据库实例:flushdb
8)、清空所有的数据库实例:flushall
9)、查看redis中所有的配置信息:config get *
查看redis中的指定的配置信息:config get parameter
11、Redis的五种数据结构:
程序是用来处理数据的,Redis是用来存储数据的;程序处理完的数据要存储到redis中,不同特点的数据要存储在Redis中不同类型的数据结构中。
字符串: zhangsan 20 true string 单key:单value: username:zhangsan age:20
list列表: 13900009999 zs@163.com 321321 list 单key:多有序value: contacts:13900009999,xxx,xxxx
set集合: beijing shanghai chongqing tianjin set 单key:多无序value:city:bj sh cq tj
pojo: id:1001,name:zhangsan,age:20 hash 单key: 对象(属性:值):
student:id:1001,name:zhangsan,age:20
zset 单key:多有序vlaue:
city:
1000 tj,1200 cq,1500 sh,2000 bj
12、redis中的操作命令:
1)、redis中有关key的操作命令:
a)查看数据库中的key:keys pattern
|->*:匹配0个或者多个字符
|->?: 匹配1个字符
|->[]:匹配[]里边的1个字符
keys *:查看数据库中所有的key
keys k*:查看数据库中所有以k开头的key
keys h*o:查看数据库中所有以h开头、以o结尾的key
keys h?o: 查看数据库中所有以h开头、以o结尾的、并且中间只有一个字符的key
keys h[abc]llo:查看数据库中所有以h开头以llo结尾,并且h后边只能取abc中的一个字符的key
b)判断key在数据库中是否存在:exists key 如果存在,则返回1;如果不存在,则返回0
exists key [key key ....] 返回值是存在的key的数量
exists k1
exists k1 k2 k3 hello
c)移动指定key到指定的数据库实例:move key index
move k 1
d)查看指定key的剩余生存时间:ttl key
|->如果key没有设置生存时间,返回-1
|->如果key不存在,返回-2
ttl k1
ttl k2
e)设置key的最大生存时间:expire key seconds
expire k2 20
f)查看指定key的数据类型:type key
type k1
g)重命名key: rename key newkey
rename hello k2
h)删除指定的key:del key [key key .....]
|->返回值是实际删除的key的数量
del k1 k2 k3 k4
2)、redis中有关string类型数据的操作命令:
a)将string类型的数据设置到redis中:set 键 值
set zsname zhangsan
set zsage 20
set totalRows 100
set zsage 30 如果key已经存在,则后来的value会把以前的value覆盖掉.
b)从redis中获取string类型的数据:get 键
get zsname
get zsage
get totalRows
c)追加字符串:append key value
|->返回追加之后的字符串长度
|->如果key不存在,则新创建一个key,并且把value值设置为value。
set phone 1389999
append phone 8888
d)获取字符串数据的长度:strlen key
strlen phone
e)将字符串数值进行加1运算:incr key
|->返回加1运算之后的数据
|->如果key不存在,首先设置一个key,值初始化为0,然后进行incr运算。
|->要求key所表示value必须是数值,否则,报错
incr zsage
incr age
incr zsname 报错
f)将字符串数值进行减1运算:decr key
|->返回减1运算之后的数据
|->如果key不存在,首先设置一个key,值初始化为0,然后进行decr运算。
|->要求key所表示value必须是数值,否则,报错
g)将字符串数值进行加offset运算:incrby key offset
|->返回加offset运算之后的数据
|->如果key不存在,首先设置一个key,值初始化为0,然后进行incrby运算。
|->要求key所表示value必须是数值,否则,报错
incrby zsage 10
h)将字符串数值进行减offset运算:decrby key offset
|->返回减offset运算之后的数据
|->如果key不存在,首先设置一个key,值初始化为0,然后进行decrby运算。
|->要求key所表示value必须是数值,否则,报错
decrby zsage 10
i)闭区间获取字符串key中从startIndex到endIndex的字符组成的子字符串:getrange key startIndex endIndex
|->下标自左至右,从0开始,依次往后,最后一个字符的下标是字符串长多-1;
|->字符串中每一个下标也可以是负数,负下标表示自右至左,从-1开始,依次往前,最右边一个字符的下标是-1
zhangsan
getrange zsname 2 5 angs
getrange zsname 2 -3 angs
getrange zsname 0 -1 zhangsan
j)用value覆盖从下标为startIndex开始的字符串,能覆盖几个字符就覆盖几个字符:setrange key startIndex value
setrange zsname 5 xiaosan //zhangxiaosan
setrange zsname 5 lao //zhanglaoosan
k)设置字符串数据的同时,设置它最大生命周期:setex key seconds value
setex k1 20 v1
l)设置string类型的数据value到redis数据库中,当key不存在时设置成功,否则,则放弃设置:setnx key value
setnx zsage 20
m)批量将string类型的数据设置到redis中:mset 键1 值1 键2 值2 .....
mset k1 v1 k2 v2 k3 v3 k4 v4 k5 v5
n)批量从redis中获取string类型的数据:mget 键1 键2 键3.....
mget k1 k2 k3 k4 k5 k6 zsname zs age totalRows
o)批量设置string类型的数据value到redis数据库中,当所有key都不存在时设置成功,否则(只要有一个已经存在),
则全部放弃设置:msetnx 键1 值1 键2 值2 .....
msetnx kk1 vv1 kk2 vv2 kk3 vv3 k1 v1
基本命令
Redis默认占用的端口号:6379
查看Redis版本:
redis-server --version
后台启动Redis:
redis-server &
关闭Redis:
redis-cli shutdown
查看Redis相关进程:
ps -ef|grep redis
连接Redis客户端:(默认连接本机6379上的Redis服务,不需密码)
redis-cli
退出客户端:
exit 或 quit
---------------------------
切换数据库:(index为0-15)
select index
添加数据:(以 k-v 形式添加)
set k1 v1
查看当前数据库所有key的数量:(0号库默认有4个数据)
dbsize
查看当前数据库所有的key:
keys *
清空当前数据库实例:
flushdb
清空所有数据库实例:(删库跑路,慎用!)
flushall
- Redis 默认启动时自动创建16个数据库实例;使用编号 0-15 给其命名;默认启动时连接第0号库
五种数据结构
string 字符串
字符串类型 string
单 key : 单 value
字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数
据,序列化后的数据,JSON 格式数据。
hash 哈希类型
哈希类型 hash
单 key : 对象(属性 : 值)
特别适合存储对象
list 列表
列表 list
单 key : 多有序 value
元素可以重复
有序:指的是按插入顺序排序
list 是最简单的字符串列表,按照插入顺序排序,底层是链表结构
set 无序集合
无序集合 set
单 key : 多无序 value
set 是 string 类型的无序无重复集合
zset 有序集合
有序无重复集合类型 zset(sorted set)
单 key : 多有序 value
有序:指的不是插入顺序,指的是会按照每个元素关联的一个分数(分数可重复)自动排序
常用操作命令
有关key的操作命令
keys xxx
作用:查看数据库中的key
可用通配符:
* 匹配0个或多个字符
?匹配1个字符
[xxx] 匹配含有中括号中任意一个字符
keys * 查看所有的key
keys k* 查看所有以k开头的key
keys a*b 查看所有以a开头,以b结尾,无论中间多少个字符的key
keys a?b 查看所有以a开头,以b结尾,并且中间只有一个字符的key
keys h[abc]llo 查看所有和 hallo,hbllo,hcllo 相同的key
exists xxx
作用:判断指定key或多个key是否存在
exists key值 判断指定key是否存在,存在则返回1,不存在则返回0
exists key1 key2 key3 ... 判断存在几个key,返回值是存在key的数量
move key index
作用:移动指定key到指定的数据库实例(使用不多)
move k1 1 移动k1元素到1号数据库实例中
expire key seconds
作用:设置指定key的生存时间
seconds 指的是单位为秒
存活倒计时是从设置完毕之后开始,倒计时结束,该key从数据库中删除
expire k1 30 设置k1存活时间为30秒
ttl key
ttl ---> time to live
作用:查看指定key的剩余生存时间
返回值意义:
-1:指没有设置该key的生存时间,即永远存在
-2:指该key在当前数据库中不存在
ttl k1 查看k1的剩余生存时间
type key
作用:查看指定key的数据类型
type k1 查看k1的数据类型(string list set hash zset)
rename key newkey
作用:重命名指定key
rename k1 k2 重命名k1为k2
del xxx
作用:删除1个或多个key
删除多个key时,key之间使用空格分隔
返回值:返回的是实际删除的key的数量
del k1 删除k1
del k1 k2 k3 删除k1 k2 k3
有关string类型操作命令
单 key 单 value
value 值均为 string 类型
set k v
作用:将string类型数据设置到redis中
如果key存在,则value覆盖
set name luis
set age 20
get k
作用:从redis中获取string类型的数据
get name
get age
append k v
作用:给指定string类型的key追加字符串
返回值:返回追加之后的字符串长度
指定追加的key不存在,则等同set,新创建
append name hh
strlen k
作用:获取指定字符串的长度
strlen phone
incr k
作用:对字符串数值进行加一运算
若指定的key不存在,则设置该key为0后,再进行加一运算
若指定的key不是字符串数值类型,则报错
incr num
decr k
作用:对字符串数值进行减一运算
若指定的key不存在,则设置该key为0后,再进行减一运算
若指定的key不是字符串数值类型,则报错
decr num
incrby k offset
作用:对字符串数值进行加自定义偏移量offset运算
若指定的key不存在,则设置该key为0后,再进行加自定义偏移量offset运算
若指定的key不是字符串数值类型,则报错
incrby num 10 对字符串数值num进行加10运算
decrby k offset
作用:对字符串数值进行减自定义偏移量offset运算
若指定的key不存在,则设置该key为0后,再进行减自定义偏移量offset运算
若指定的key不是字符串数值类型,则报错
decrby num 10 对字符串数值num进行减10运算
getrange k startIndex endIndex
作用:截取字符串k从startIndex到endIndex的子字符串(闭区间截取)
返回值:截取的子字符串
下标自左向右,从0开始,逐次加一,最后一个字符的下标为字符串长度减一
下标可以为负数,为负数时,最后一个字符下标为-1,往左则为-2,-3,-4等
截取后不改变原数据
截取的是key对应的value子字符串
下标区分:
大于等于0,则自左向右数:依次为 0 1 2 3 4 ...
小于0,则自右向左数:依次为 -1 -2 -3 -4 ...
getrange k 1 3
getrange k -3 -1
getrange k 1 -1
setrange k startIndex v
作用:用v覆盖从下标为startIndex开始的字符串,能覆盖几个覆盖几个
setrange k 1 abc
setex k seconds v
作用:设置字符串数据的同时,设置其最大生命周期
若key值相同,则value覆盖,并设置最大声明周期
ex:expire
seconds:秒
setex k 20 test
setnx k
作用:设置字符串类型数据value到redis数据库,若key存在,则放弃设置
setnx:set not exists
setnx k kkkkkk
mset xxx
作用:批量设置string类型数据到redis中
语法:mset k1 v1 k2 v2 k3 v3 ...
mset k1 v1 k2 v2 k3 v3
mget xxx
作用:批量获取string类型的数据
语法:mget k1 k2 k3 k4
mget k1 k2 k3 k4
msetnx xxx
作用:批量设置string类型数据;当所有key都不存在时,设置成功;只要至少有一个key已经存在,则放弃批量设置。
语法:msetnx k1 v1 k2 v2 k3 v3 ...
返回值:批量设置成功返回1;批量设置失败则返回0
msetnx k1 v1 k2 v2 k3 v3 ...
有关list类型操作命令
list 列表类型是有序可重复的
单 key 多 value
存储的多value值均为string类型
list的有序,指的是按照插入顺序排序;有下标
左边为表头,右边为表尾
从左到右下标可表示为:0 1 2 3 4 ...
从右到左下标可表示为:-1 -2 -3 -4 ...
lpush k xxx
作用:将一个或多个值依次插入到列表的表头(左侧)
语法:lpush k v1 v2 v3
注意:每次最新插入的元素都是从表头处插入的
lpush list01 1 2 3 4
lrange k startIndex endIndex
作用:获取指定列表指定下标区间的所有元素
lrange list01 0 -1 获取list01列表中所有元素(获取列表所有元素,常用)
rpush k xxx
作用:将一个或多个值依次插入到列表的表尾(右侧)
语法:rpush k v1 v2 v3
注意:每次最新插入的元素都是从表尾处插入的
rpush list02 1 2 3 4
lpop k
作用:从指定列表中移除表头(左侧)元素
返回值:移除的元素
lpop list02
rpop k
作用:从指定列表中移除表尾(右侧)元素
返回值:移除的元素
rpop list02
lindex k index
作用:获取指定列表指定下标位置的元素
lindex list02 1
llen k
作用:获取指定列表的长度
llen list02
lrem k count v
作用:根据 count 值移除指定列表中和 value 相等的元素
当 count = 0,从列表中移除所有与 value 值相等的元素
当 count > 0,从列表左侧开始,移除 count 个与 value 值相等的元素
当 count < 0,从列表右侧开始,移除 count 个与 value 值相等的元素
lrem list02 0 a 移除列表list02中所有和a相同的元素
lrem list02 2 a 从列表list02左侧开始,移除2个和a相同的元素
lrem list02 -2 a 从列表list02右侧开始,移除2个和a相同的元素
有关set类型操作命令
set 无序不可重复集合
单 key 多无序 value
特点:无下标、通过 key 操作集合
集合类型的数据操作总的思想是通过 key 确定集合,key 是集合标识,元素没有下标,直接操作业务数据和数据的个数。
sadd k xxx
作用:将一个或多个元素添加到指定的集合中
返回值:添加成功的元素个数
注意:添加的元素不可重复,且无序
sadd set01 a c c b d
smembers k
作用:获取指定set集合中所有元素
smembers set01
sismember k member
作用:判断指定元素在指定集合中是否存在
返回 0:则不存在
返回 1:则存在
sismember set01 a
scard k
作用:获取指定集合的长度
scard set01
srem k xxx
作用:移除指定集合中一个或多个元素(元素不存在则忽略)
返回值:成功移除元素的个数
srem set01 a c d
srandmember k [count]
作用:从指定集合中随机获取一个或多个元素
count 可加可不加
不加,默认是从指定集合中随机获取一个元素
当 count > 0,则从指定集合中随机获取不重复的 count 个元素
当 count < 0,则从指定集合中随机获取可能重复的 count 个元素
适用场景:抽奖活动
srandmember set01
srandmember set02 2
srandmember set02 -2
spop k [count]
作用:从指定集合中随机移除一个或多个元素
返回值:移除的元素
应用场景:抽奖活动,中奖后从名单中移除中奖者
spop set02 2
smove source dest member
作用:将指定集合中指定元素移动到另一个集合中
smove set1 set2 2 将集合set1中的元素2移动到集合set2中
sdiff k xxx
作用:获取第一个集合中有,其他集合中都没有的所有元素组成的新集合【求差集】
“其他集合”可以有一个或多个
sadd s1 a b c 1 2 3
sadd s2 b c
sadd s3 2 3
sdiff s1 s2 s3 结果:a 1
sinter k xxx
作用:获取指定集合中都有的元素组成的新集合【求交集】
求交集的集合可以有两个或两个以上
sadd s1 a b c 1 2 3
sadd s2 b c 3
sadd s3 2 3
sinter s1 s2 s3 结果:3
sunion k xxx
作用:获取所有指定集合中所有元素组成的大集合【求并集】
求并集的集合可以有两个或两个以上
集合中无重复元素
sadd s1 a b c
sadd s2 1 2 3
sadd s3 a 1
sinter s1 s2 s3 结果:a b c 1 2 3
有关hash类型操作命令
单 key 多 value(键值对)
数据格式示例:
key:field-value field-value field-value ...
Redis 的 hash 是一个 string 类型的 key 和 value 的映射表,这里的 value 是一系列的键值对,hash 特别适合用于存储对象。
哈希类型的数据操作总的思想是通过 key 和 field 操作 value,key 是数据标识,field 是域,value 是我们感兴趣的业务数据。
hset k field v
作用:将一个或多个 field-value 对设置到 hash 表中
语法:
hset key field value [field value ,,,]
注意:field-value 可设置一个或同时设置多个【
hset
和hmset
作用相同,均可批量设置】如果 key 和 field 已存在,则进行 value 覆盖
hset stu1 name jack
hset stu2 name luis age 20
hsetnx k field v
作用:将一个 field-value 键值对设置到指定 hash 表中
注意:
- 此 field-value 设置方法仅仅针对一个键值对有效,不能同时设置多个
- 如果 key 和 field 已存在,则放弃设置
- 如果 key 和 field 都不存在,则设置 field-value 到新的 hash 表中
- 如果 key 存在,field 不存在,则设置 field-value 到该指定的已存在的 hash 表中
hsetnx stu1 name luis
hget k field
作用:获取指定 hash 表中指定 field 的值
hget stu1 name
hget stu2 age
hmget k xxx
作用:批量获取指定 hash 表多个 field 的值
语法:
hmget key field [field ...]
hmget stu2 name age
hgetall k
作用:获取指定 hash 表中所有 field 和 value
hgetall stu2
hdel k xxx
作用:从指定 hash 表中删除一个或多个 field
语法:
hdel key field [field ...]
hdel stu1 name age
hlen k
作用:获取指定 hash 表中 field 个数
hlen stu1
hexists k field
作用:判断指定 hash 表中是否存在指定 field
返回 1,则存在
返回 0,则不存在
hexists stu1 name
hkeys k
作用:获取指定 hash 表中所有的 field 列表
hkeys stu1
hvals k
作用:获取指定 hash 表中所有的 value 列表
hvals stu1
hincrby k field int
作用:对指定 hash 表中指定 field 值进行整数加法运算
hincrby stu1 age 5 对哈希表stu1的age属性值进行加5运算
hincrbyfloat k field float
作用:对指定 hash 表中指定 field 值进行浮点数加法运算
hincrbyfloat stu1 score 0.5
有关zset类型操作命令
有序集合 zset
Redis 有序集合 zset 和集合 set 一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是 zset 的每一个元素都会关联一个分数(分数可重复),redis 通过分数来为集合中的成员进行从小到大的排序。
总结:
- 有序不可重复的 string 类型元素集合
- 根据每个元素关联的分数进行自动排序,分数可重复
- 有下标
zadd k score member
作用:将一个或多个 member 以及 score 值加入有序集合 zset 中(自动根据 score 值从小到大进行排序)
语法:
zadd key score member [score member ...]
如果集合中元素已存在,则进行分数覆盖(分数覆盖后,元素会进行重新排序)
zadd zset01 20 b 10 a 30 c zset01结果:a b c
zadd zset01 60 a zset01结果:b c a
zrange k startIndex endIndex [withscores]
作用:获取指定有序集合指定下标区间的所有元素(加上
withscores
则元素对应的分数也可获取到)注意:
zrevrange
与zrange
相反
zrange
是按照分数从小到大获取所有元素
zrevrange
是按照分数从大到小获取所有元素
zrange zset01 0 -1 获取有序集合zset01所有元素(不带分数)
zrange zset01 0 -1 withscores 获取有序集合zset01所有元素(带分数)
zrangebyscore k min max [withscores]
作用:获取指定有序集合中指定分数区间(闭区间)的所有元素(可选择带分数获取)
zrangebyscore zset01 20 60
zrangebyscore zset01 20 60 withscores
zrem k member
作用:删除指定有序集合中一个或多个元素
语法:
zrem key member [member ,,,]
zrem zset01 a c
zcard k
作用:获取指定有序集合中所有元素的个数
zcard zset01
zcount k min max
作用:获取指定有序集合中分数在指定区间内(闭区间)元素的个数
zcount zset02 20 40
zrank k member
作用:获取指定有序集合中指定元素的排名(从0开始)(按照分数从小到大)
zrank zset01 a
zrevrank k member
作用:获取指定有序集合中指定元素的排名(从0开始)(按照分数从大到小)
zrevrank zset01 a
zscore k member
作用:获取指定有序集合中指定元素的分数
zscore zset01 a
Redis 的配置文件
redis.conf 配置文件
- 存放位置:在 redis 安装目录下名为 redis.conf
- 可配置一些 redis 服务端运行时的一些参数,不配置则使用默认的参数
- 如果对配置文件进行了参数配置,在启动 redis 服务时必须指定所使用的配置文件
Redis 的网络相关配置
- port:可指定 redis 服务所使用的端口,默认使用 6379
- bind:配置客户端连接 redis 服务时,所能使用的 IP 地址,默认可使用 redis 服务所在主机上任何一个 IP 均可;但一般情况下,都会配置一个 IP,而且通常是一个真实的 IP 地址。
- tcp-keepalive:连接保活策略
如果配置了 port 和 bind,则启动 redis 服务时,必须指定配置文件;客户连接 redis 服务时,必须指定端口和 IP,如:
redis-server redis.conf & 后台启动redis服务,指定配置文件
redis-cli -h 192.168.11.128 -p 6380 连接redis服务
redis-cli -h 192.168.11.128 -p 6380 shutdown 关闭redis服务
Redis 的常规配置
- loglevel:日志级别,开发阶段可设置成 debug,生产阶段通常设置为 notice 或 warning。
- logfile:指定日志文件名,如果不指定,Redis 会进行标准输出到控制台;指定日志文件名的时候,需要保证日志文件所在目录必须存在,文件可以不存在;配置之后需要在 Redis 启动的时候指定所使用的配置文件,否则配置不起作用。
- databases:配置 Redis 数据库的个数,默认是 16 个。
Redis 的安全配置
- requirepass:配置 Redis 的访问密码。默认不配置,即访问不需密码验证。此配置项需要在配置 protected-mode=yes 时起作用。并且配置后,必须使用密码登陆客户端,如:
redis-cli -h ip -p 6379 -a pwd
Redis 的持久化
Redis 提供持久化策略,在适当的时机采用适当手段把内存中的数据持久化到磁盘中,每次 Redis 服务启动时,都可以把磁盘上的数据再次加载到内存中使用。
RDB 策略
在指定的事件间隔内,Redis 服务执行指定次数的写操作,会自动触发一次持久化操作。
RDB 策略是 Redis 默认的持久化策略,Redis 服务开启时,这种持久化策略就已经默认开启了。
可配置的几个参数:
save <seconds> <changes>
:配置持久化策略,指定时间内执行指定次数写操作自动触发持久化dbfilename
:配置 redis RDB 持久化数据存储的文件dir
:配置 Redis RDB 持久化文件所在目录
AOF 策略
采用操作日志来记录进行每一次的写操作,每次 Redis 服务启动时,都会重新执行一次操作日志中的指令。
效率低下,Redis 默认不开启 AOF 功能。
可配置的一些参数:
appendonly
:配置是否开启 AOF 策略appendfilename
:配置操作日志文件
小结:
- 根据数据特点决定开启哪种持久化策略
- 一般情况,开启 RDB 已足够
Redis 的事务
事务:把一组数据库命令放在一起执行,保证操作原子性,要么同时成功,要么同时失败。
Redis 的事务:允许把一组 redis 命令放在一起,把命令进行序列化,然后一起执行,保证部分原子性。
事务的开启与执行
Redis 中使用multi
命令标记一个事务的开始,使用exec
来执行事务队列中所有的命令。
示例:
multi
set k1 v1
set k2 v2
exec
Redis 事务只可保证部分原子性
Redis 的事务只能保证部分原子性
如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有命令都不执行,可保证事务的原子性。如:
multi
set k2 v2
seta k3 v3 此处命令书写错误,导致本事务中所有事务均不执行
set k4 v4
exec
执行结果:全部命令都不会执行。
如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,不影响其他正确命令的执行,这种情况下,就无法保证事务的原子性。如:
multi
set k2 v2
incr k1 此处语法正确,但此时未执行命令,无法判断k1是否为字符串数值,所以只会在执行事务命令时失败
set k3 v3
exec
执行结果:部分命令执行失败,其他命令执行成功,Redis 的事务只能保证部分原子性。
中止并结束事务
在事务过程中,可使用discard
命令清除所有已压入队列中的命令,并且结束整个事务。如:
multi
set k1 v1
set k2 v2
discard 中止并结束整个事务
监控键值变化
在开启事务前,可使用watch
命令监控某一个键,当事务在执行过程中,若监控的键的值发生变化,则当前事务放弃执行;否则,正常执行。示例:
set balance1 100
set balance2 1000
set version 1
watch version 监控version键,若事务过程中此键的值变化,则最后事务放弃执行!
multi
decrby balance1 50
incrby balance2 50
incr version
exec 此事务执行的条件是version值与原先值一样,未发生改变!
放弃监控键值变化
可使用unwatch
命令放弃监控所有的键,当放弃监控所有的键时,事务的执行不再受监控!(符合一定条件才使用放弃监控)
set balance1 100
set balance2 1000
set version 1
watch version
unwatch 放弃监控version,事务执行不再受监控。
multi
decrby balance1 50
incrby balance2 50
incr version
exec
Redis 事务小结
- 单独的隔离操作:事务中的所有命令都会序列化、顺序地执行。事务在执行过程中,不会被其他客户端发来的命令请求所打断。
- 不保证事务的原子性:Redis 同一个事务中如果一条命令执行失败,其后的命令仍然可能会被执行,Redis 的事务没有回滚。Redis 已经在系统内部进行功能简化,这样可以保证更快的运行速度,因为 Redis 不需要事务回滚的能力。
Redis 消息的发布与订阅(了解)
了解即可,后面基本不用,会使用如 ActiveMQ、RabbitMQ、Kafka 等消息队列中间件代替此功能。
Redis 发布订阅( pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可订阅任意数量的频道。
情景模拟:多个 Redis 客户端操作同一个 Redis 服务器,若其中一个客户端对服务器中某一数据进行改变,需要通知其他可能会使用此数据的客户端。需要使用此数据的客户端可订阅一个频道,此数据改变后某客户端直接向此频道发送消息,其他订阅了此频道的客户端都会收到消息。
Redis 客户端订阅频道,消息的发布者往频道上发布消息,所有订阅此频道的客户端都能接收到消息。
相关命令:
-
subscribe
:订阅一个或多个频道的消息(频道名支持通配符)subscribe ch1 ch2 ch3 subscribe news.* subscribe ch.*
-
publish
:将消息发布到指定频道publish ch1 message
Redis 的主从复制
主机数据更新后根据配置和策略,自动同步到从机的 master/slave 机制,Master 以写为主,Slave 以读为主。
特点:主少从多、主写从读、读写分离、主写同步复制到从。
注意:一个从机可以有多个从机,但一个从机只能从属于一个主机。
搭建一主二从 redis 集群
在一台服务器上模拟搭建一主二从 redis 集群,实际工作中是一个 redis 配一个服务器。
此处使用一台服务器,一个 Redis 软件中分别配置三个不同端口启动 Redis 服务来进行模拟。
1.修改三份配置文件
修改配置文件前先关闭之前的 redis 服务
搭建三台 redis 服务:使用一个 redis 模拟三台 redis 服务
提供三份 redis 配置文件:redis6379.conf、redis6380.conf、redis6381.conf
分别修改三份配置文件,此处以 redis6379.conf 为例,分别需要在配置文件中修改以下一些参数:
bind 127.0.0.1
port 6379
pidfile /www/server/redis/redis_6379.pid
logfile "/www/server/redis/redis_6379.log"
dbfilename dump_6379.rdb
2.启动三个 redis 服务
分别使用三个 redis 配置文件,启动三个 redis 服务
最好开启三个会话窗口,每个会话窗口中分别启动一个 redis 服务
注意:使用配置文件启动 redis 服务时最好切换到配置文件所在目录,因为可以直接使用配置文件的相对路径
分别在三个会话窗口中,配置文件所在目录下,分别后台启动三个 redis 服务:
redis-server redis6379.conf &
redis-server redis6380.conf &
redis-server redis6381.conf &
启动后可使用 ps -ef|grep redis 查看是否启动成功(因为配置日志信息到日志文件中,所以控制台无相关打印输出),查询如下:
[root@linwei redis]# ps -ef|grep redis
root 15452 1 0 19:32 ? 00:00:00 redis-server 127.0.0.1:6379
root 15585 1 0 19:33 ? 00:00:00 redis-server 127.0.0.1:6380
root 15729 1 0 19:34 ? 00:00:00 redis-server 127.0.0.1:6381
root 15750 15055 0 19:34 pts/2 00:00:00 grep --color=auto redis
以上,则成功模拟在一个服务器上分别启动三个 redis 服务。
3.连接三个 redis 服务
通过 redis 客户端分别连接三个 redis 服务:
redis-cli -h 127.0.0.1 -p 6379
redis-cli -h 127.0.0.1 -p 6380
redis-cli -h 127.0.0.1 -p 6381
连接成功后可使用 keys * 命令查看是否有数据,有数据则清理掉,保证数据干净,方便后续测试!
4.查看三台 redis 服务在集群中的主从角色
使用info replication
命令分别查看三台 redis 服务在集群中的主从角色!
下面以 6379 端口的 redis 查看的信息为例:
127.0.0.1:6379> info replication
# Replication
role:master 角色为主机
connected_slaves:0 没有从机连接
master_failover_state:no-failover
master_replid:d748ea134e85360248197bf9bd2f91bdba02ef9a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
默认情况下,所有的 redis 服务都是主机,即都能写和读,但是都还没有从机。
5.验证三台 redis 服务是否独立
在 6379 端口的 redis 服务上进行写操作:
set k1 v1
keys *
查看其他两个端口的 redis 服务中是否有写入的数据!
验证结果:三台 redis 服务互相独立,互不影响。
6.设置主从关系
设置主从关系——一主二从
PS:此处将 6379 作为主机,6380 和 6381 作为 6379 的从机
设置原则:设从不设主(主机不用设置,只需要设置从机即可)
在 6380 上设置其为 6379 的从机,并查看主从关系变化:
slaveof 127.0.0.1 6379
info replication 可查看到角色变为从机
在 6381 上设置其为 6379 的从机,并查看主从关系变化:
slaveof 127.0.0.1 6379
info replication 可查看到角色变为从机
在 6379 上查看主从关系变化:
info replication 可查看到有两个从机连接
7.全量复制
全量复制:一旦主从关系确定,则从机会自动将主机上已有的数据复制过来。
验证:之前主从关系未确定时,6379 主机上0号库有一条写入的数据;主从关系确定后,在 6380 从机和 6381 从机上使用keys *
命令可查看到之前 6379 写入的一条数据已经同步过来!
8.增量复制
增量复制:主库写数据将会自动同步到从库
验证:在 6379 主机上执行写操作 set k2 v2
,在 6380 从机和 6381 从机上使用keys *
可查看到在 6379 主机上写入的数据。
9.主写从读,读写分离
主写从读,读写分离
- 主机可读可写,但一般主机都用来进行写操作,读操作交给从机
- 从机只能进行读的操作,不能进行写的操作
- 主机和从机职责分明,读写分离
验证:分别在 6380 从机和 6381 从机上进行写的操作:set k3 v3
结果:从机无法进行写的操作
127.0.0.1:6380> set k3 v3
(error) READONLY You can't write against a read only replica.
127.0.0.1:6381> set k3 v3
(error) READONLY You can't write against a read only replica.
10.主机宕机,从机原地待命
主机宕机,从机原地待命:主机服务停止,从机从属关系不变,权限不变,只是原地待命,连接状态由 up 变为 down。
关闭 6379 服务,模拟主机宕机:
redis-cli -h 127.0.0.1 -p 6379 shutdown
ps -ef|grep redis
查看 6380 和 6381 的主从角色是否变化:
info replication
结果:主机宕机,从机主从角色不会变化,从机原地待命
11.主机恢复,一切恢复
重启 6379 服务:(最好在配置文件目录下,直接使用配置文件的相对路径)
redis-server redis6379.conf &
ps -ef|grep redis
客户端连接 redis 服务:
redis-cli -h 127.0.0.1 -p 6379
分别查看三台 redis 服务的主从关系以及相关状态:
info replication
结果:主机恢复,从机重新激活,一切恢复正常。
12.从机宕机,主机少一从机,其他从机不变
关闭 6380 从机服务:(退出连接状态后才能关闭服务)
redis-cli -h 127.0.0.1 -p 6380 shutdown
ps -ef|grep redis
查看 6379 主机和 6381 从机的主从角色:
info replication
结果:从机宕机,主机少一从机,其他从机不变。
13.从机恢复,需重新设置主从关系
重启 6380 服务:(在配置文件所在路径,直接使用相对路径)
redis-server redis6380.conf &
ps -ef|grep redis
客户端连接 redis 服务:
redis-cli -h 127.0.0.1 -p 6380
分别查看三个端口主从关系:
info replication
结果:
- 重新恢复的 6380 主从关系由从机变为主机,没有从机连接
- 之前的主机 6379 仍然是主机,仍然只有 6381 一个从机连接
- 6381 从机状态一直正常
结论:从机恢复,主从关系需要重新设置
重新设置 6380 为 6379 的从机:
slaveof 127.0.0.1 6379
重新查看 6380 和 6379 的主从关系:
info replication
结果:6380 成为 6379 的从机;6379 有 6380 和 6381 两个从机
最终结论:从机恢复,需重新设置主从关系
14.从机上位
背景:在主机宕机,从机原地待命的情况下,若主机无法恢复或者需要耗费长时间才能恢复,此时可以让一台从机担任主机,上位成为主机,让其他从机从属于它。
a.主机宕机,从机原地待命
关闭 6379 服务,模拟主机宕机:
redis-cli -h 127.0.0.1 -p 6379 shutdown
ps -ef|grep redis
查看 6380 和 6381 的主从角色是否变化:
info replication
结果:主机宕机,从机主从角色不会变化,从机原地待命
b.从机断开原来主从关系
此处选择 6380 作为待上位的新主机。
在 6380 上执行命令,断开主从关系:
slaveof no one
查看 6380 主从关系:
info replication
结果:6380 成为主机,没有从机连接
c:重新设置主从关系
原则:设从不设主
在 6381 上执行命令,将其设置为 6380 的从机:
slaveof 127.0.0.1 6380
分别查看 6381 和 6380 的主从关系:
info replication
结果:6381 成为 6380 的从机;6380 上位成功,成为主机,有 6381 一个从机连接
15.之前主机恢复,变成孤家寡人
重启 6379 服务:(在配置文件所在目录执行,使用相对路径)
redis-server redis6379.conf &
ps -ef|grep redis
客户端连接 6379 redis 服务:
redis-cli -h 127.0.0.1 -p 6379
查看 6379 主从关系:
info replication
结果:6379 为主机,无从机连接
结论:由于从机上位成功,之前的主机长时间才恢复,之前的从机不在从属于它,如今其变为孤家寡人,游离在系统之外。
16.天堂变地狱
由于之前的主机恢复,但是有从机已经上位,在此让恢复的 6379 成为从机 6381 的从机。
注意:一个从机可以有多个从机,但一个从机只能从属于一个主机。
在 6379 上执行命令,使其成为 6381 的从机:
slaveof 127.0.0.1 6381
分别查看 6379 和 6381 的主从关系:
info replication
结果:6379 成为从机 6381 的从机;6381 从属于 6380,但其下还有 6379 这个从机。
小结
一台主机可配置多台从机,一台从机又可配置多台从机,从而形成一个庞大的集群架构。
此架构减轻了一台主机的压力,但是增加了服务间的延迟时间。
Redis 哨兵模式
Redis 哨兵模式其实就是主机宕机,从机上位的自动版。
因为无法知晓主机何时宕机或者说无法实时对主机宕机行为做人工监测,所以哨兵模式就出现了,它可以实时监测主机的情况,当主机宕机时,会按照一定的策略,选择一个从机上位,从而不影响系统的运行。
主机宕机,从机上位其实就是先将待上位的从机解除主从关系,然后设置其他从机都从属于它。
哨兵模式实现示例:
1.搭建一主二从集群架构
PS:沿用之前搭建的前六步即可
当前状态:一主二从—— 6379 主,6380 从,6381 从
2.提供哨兵配置文件
新开会话窗口,在 redis 目录下创建 redis_sentinel.conf
文件,将下列配置写入文件:
sentinel monitor dc-redis 127.0.0.1 6379 1
上列配置表示:指定监控主机的 IP 地址,port 端口,得到哨兵的投票数(当哨兵投票数大于或者等于此数时切换主从关系)
3.启动哨兵
在哨兵配置文件所在路径执行下列命令启动哨兵:
redis-sentinel redis_sentinel.conf
以上,则成功启动哨兵模式
4.演示主机宕机情况
演示主机宕机,哨兵监测到后,使用一定策略,进行投票,自动选择一个从机上位。
关闭 6379 服务:
redis-cli -h 127.0.0.1 -p 6379 shutdown
ps -ef|grep redis
可在观察到哨兵服务后台输出打印相关信息后,查看 6380 和 6381 的主从关系:
info replication
结果:6380 成为主机,6381 成为 6380 的从机。
结论:主机宕机后,哨兵程序自动选择从机上位。
4.之前主机恢复,自动从属新的主机
重启 6379 服务:(在配置文件所在路径执行,使用文件的相对路径)
redis-server redis6379.conf &
ps -ef|grep redis
客户端连接 6379 redis 服务:
redis-cli -h 127.0.0.1 -p 6379
查看 6379 和 6380 的主从关系:
info replication
结果:6379 成为 6380 的从机;6380 有 6379 和 6381 两个从机
结论:之前主机恢复,自动从属新的主机
小结
redis-server 配置文件名 & 使用配置文件启动redis服务(在配置文件所在目录,可使用相对路径)
ps -ef|grep redis 查看redis服务启动情况
redis-cli -h IP地址 -p 端口号 使用配置文件方式的客户端连接redis服务
redis-cli -h IP地址 -p 端口号 shutdown 使用配置文件方式关闭redis服务
info replication 查看主从复制关系
slaverof 主机IP 主机端口 设置主从关系
redis-sentinel 哨兵配置文件名 启动哨兵模式(在哨兵配置文件所在路径,使用相对路径)
主从复制原则:开始时全量复制,之后是增量复制
哨兵模式三大任务:监控、提醒、自动故障迁移
Redis主从复制最大缺点:延迟
主机负责写,从机负责备份,此过程有一定延迟,当系统很繁忙时,延迟问题会更加严重,从机数量的增加也会使延迟问题严重化。
Jedis 操作 Redis
Jedis 其实就是将 Redis 所有操作命令实现好的一套 Java 类库
使用 Redis 官方推荐的 Jedis,在 Java 应用中操作 Redis
Jedis 几乎涵盖了 Redis 的所有命令
操作 Redis 的命令在 Jedis 中以方法的形式出现
下面是 Jedis 操作 Redis 的示例,其他操作方式相同,类推。
在 Java 中使用 Jedis 操作 Redis 的步骤:
旧1. 改 IP 地址,运行 Redis 服务
- 需要在 Redis 配置文件中将 6379 端口所在配置文件中的 IP 地址由 127.0.0.1 改为本机真实地址:192.168.1.8
因为 127.0.0.1 的 IP 地址只能在本机上访问,后面需要用 Java 连接 Redis,需要配置 IP 地址为本机器的真实 IP 地址(本机的真实 IP 地址可以在 DOS 窗口使用 ifconfig 命令查看)
-
使用配置文件方式后台启动 Redis 服务(在配置文件所在路径执行,可直接使用配置文件的相对路径)
redis-server redis6379.conf & ps -ef|grep redis
实际上,按照以上方式没能启动redis服务,最后使用新1方式,可在Java中正常连接上!
新1. 注释 IP 地址,设置 protected-mode 为 no,运行 Redis 服务
实际上,我使用的是自己的云服务器上安装的 Redis 服务
可先在自己电脑上的 DOS 命令窗口 ping 下自己的云服务器公网 IP,如我的ping 47.103.71.201
正常 ping 通是 Java 中使用该 IP 正常连接 Redis 的前提
注意:使用云服务器需要放行 6379 端口!
然后修改 redis 的配置文件:
- 注释掉 bind
- 设置
protected-mode 为 no
然后使用指定的配置文件启动 Redis 服务:(在配置文件所在路径执行,可直接使用配置文件的相对路径)
redis-server redis6379.conf &
ps -ef|grep redis
最后在 Java 测试代码中使用 ping 通的公网 IP 47.103.71.201 和 6379 端口连接 Redis 即可。
2.新建 maven web 模块
- 其实此处只是演示使用 Jedis 连接 Redis 服务,操作数据,创建 web 或 Java 项目均可,但一般开发都是创建 web 项目
3.添加 Jedis pom 依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
4.创建测试类
public class JedisKeyTest {
public static void main(String[] args) {
// 连接 Redis
Jedis jedis = new Jedis("47.103.71.201", 6379);
// System.out.println(jedis.ping());
Set<String> keys = jedis.keys("*");
for (String key : keys) {
System.out.println(key);
}
Long k2 = jedis.move("k2", 1);
String s = jedis.select(1);
String k1 = jedis.get("k1");
// 获取事务对象,通过事务对象操作数据
Transaction trans = jedis.multi();
trans.set("a", "a");
trans.set("b", "b");
trans.exec(); // 提交事务
}
}
练习:将之前 redis 中常用的命令,在 Java 中调用 Jedis 的方法都练习一次!
都看到最后了,右下角来个赞鸭!-.- 欢迎评论留言~