1.Redis:能够存储数据、管理数据的一种软件
redis支持key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。支持数据备份,master-slave模式的数据备份
2.数据库应用发展历程:
单机数据库时代:一个应用,一个数据库实例
缓存、水平切分时代:
读写分离时代:
分表分库时代(集群):
关系型数据库:Oracle、Mysql、DB2、SQLServer
非关系型数据库(Nosql):底层改变存储机制。不再采用关系数据模型,聚合数据结构存储。
redis、mongoDb、HBase、
3.安装redis:
官网:http://redis.io
压缩包放进linux opt包
tar -zxvf redis-5.0.2.tar.gz -C /opt
编译 redis,进入解压目录,并且执行 make 命令
有外网安装gcc 命令:yum -y install gcc
# 清除make命令:make distclean (可清除缓存,再make)
执行 make install 安装 redis:
注意:在make执行之后再执行 make install,该操作则将 src下的许多可执行文件复制到/usr/local/bin 目录下,这 样做可以在任意目录执行redis的软件的命令(例如启动,停止,客户端连接服务器等), make install 可以不用执行, 看个人习惯。
查看make编译结果,cd src目录
4.启动redis
1)前台启动默认配置文件:redis-server
2)后台启动默认配置文件:redis-server &
mysql端口:3306 redis端口:6379
查询是否启动:ps -ef|grep redis
更改redis默认端口号 配置文件:redis.conf
5.启动redis服务时,指定配置文件:redis-server redis.conf &
6.关闭redis服务
1)通过kill命令
ps -ef|grep redis 查询PID
kill -9 PID
2)通过redis命令关闭
redis-cli shutdown
7.redis客服端:用来连接redis服务,向redis服务端发送命令,并且显示redis服务处理结果。
redis-cli:redis自带的客户端
redis-cli:默认连接127.0.0.1(本机)的6379端口上的redis服务
redis-cli -p 端口号:连接127.0.0.1(本机)的指定端口上的redis服务。
redis-cli -h ip地址 -p 端口:连接指定ip主机上的指定端口的redis服务。
8.退出客户端:
在客户端执行命令:exit或quit
9.redis的基本知识
1)测试redis服务的性能:redis-benchmark
2)查看redis服务是否正常运行:ping 如果正常–>pong
3)查看redis服务器的统计信息:
info:查看服务器所用统计信息
info [信息段] 查看redis服务器的指定的统计信息 如:info Replication
4)redis的数据库实例:
作用类似于mysql的数据库实例,redis中的数据库实例只能由redis服务来创建和维护。开发人员不能修改和自行创建数据库实例:默认情况下,redis会自动创建16个数据库实例,并且给16个数据库实例编号,从0-15,使用时用编号代表数据库。可以使用配置文件来指定创建多少个数据库实例。数据库实例本身所占内存很少,不会对存储空间造成浪费。
默认情况下,redis客户端连接的是编号是0号的数据库实例 可以使用select index切换数据库实例 如:select 2;
5)查看当前数据库实例中key条数:dbsize
6)查看当前数据库实例所有的key:keys *
7) 清空数据库实例:flushdb
8)清空所有数据库实例:flushall
9)查看redis的配置信息:config get *
查看redis的指定配置信息:confir get parameter
10.redis的5种数据结构
程序是用来处理数据的,redis是用来存储数据的;程序处理完的数据存储在redis中,不同特点的数据要存储到redis不同类型的数据结构中。
11.redis的操作命令
1)redis中有关key的操作命令
b)判断key是否存在数据库中, exists k1或exists k1 k2 k3,返回对应存在key的数量
c)移动指定key到指定数据库中去 move key index 例:move k1 1
d)查看指定key的剩余生存时间:ttl key
|—>ttl k1 如果数据库没有该key,则返回-2;如果key没有设置生存时间则返回-1
e)设置key的最大生存时间:expire key seconds 例:expire k2 20
f)查看指定key的数据类型:type key 例:type k1
g)重命名key:rename key newkey 例:rename k1 key
h)删除key:del key[key key ···]
|—>删除指定key,返回删除key的个数 例:del k1 k2 k3
2)redis有关string数据类型操作的命令 单key-单value
a)将string类型数据设置到redis中:set key value 例子 set k1 1
b)从redis中获取string类型数据:get key 例:get k1
c)追加字符串:append key value
|–>返回追加之后字符串长度
|–>如果key不存在,则创建新的key
d)获取string类型长度:strlen key 例:strlen k1
e)将字符串数值进行加1运算:incr key
|–>返回+1之后的字符串数据
|–>如果key不存在,先创建一个key,初始值为0,再进行incr运算
|–>要求key的value必须是数值,不然报错
f)将字符串数值进行减1运算:decr key
|–>返回减1之后的字符串数据
|–>如果key不存在,先创建一个key,初始值为0,再进行decr运算
|–>要求key的value必须是数值,不然报错
g)将字符串数据进行加固定值offset运算:incrby key offset
|–>返回加offset运算之后的字符串数据
|–>如果key不存在,先创建一个key,初始值为0,再进行加offset运算
|–>要求key的value必须是数值,不然报错
h)将字符串数据进行减固定值offset运算:decrby key offset
|–>返回减offset运算之后的字符串数据
|–>如果key不存在,先创建一个key,初始值为0,再进行减offset运算
|–>要求key的value必须是数值,不然报错
i)闭区间获取字符串中从startIndex到endIndex的字符组成的子字符串:getrange key startIndex endIndex
|–>下标从0开始到length()-1(自左到右)
|–>下标也可以是负数,负下标表示从右到左,从-1开始,依次往前,直到-length()
j)用value覆盖从下标为startindex开始的字符串,能覆盖几个字符就覆盖几个字符:setrange key startIndex value
|—>setrange name 5 xiaosan 结果:zhangxiaosan
|—>setrange name 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
3)redis中对list数据类型数据操作命令 单key-多有序value
|–>多个value之间有顺序,最左侧是表头,最右侧是表尾,
|–>从左到右,下标是0-length-1。从右到左,下标是-1-负length
|–>元素的顺序由放入的顺序或者下标由放入的顺序决定
a)将一个或多个值插入列表表头(左侧):lpush key value [value value]
|–>先放后出类似栈 lpush list 1 2 3 ==>3 2 1
|–>lpush list 5 4 ==> 4 5 3 2 1
|–>返回值是表中有多少元素
b)获取指定list列表指定下标元素:lrange key startIndex endIndex
|–>例:lrange list 1 2 ==>2 1
c)将一个或多个值插入列表表尾(右侧):rpush key value [value value]
|–>先放先出类似队列 rpush list01 a b c ==> a b c
|–>lpush list01 d e ==> e d a b c
|–>返回值是表中有多少元素
d)从指定列表中移除并返回表头元素:lpop key
|–>lpop list01 ==> e
e)从指定列表中移除并返回表尾元素:rpop key
|–> rpop list01 ==> c
f)获取列表中指定下标的元素:lindex key index
|–>lindex list 3 ==> 2
g)获取指定列表长度:llen key 例:llen list
h)根据count值移除指定列表跟value相等的数据:lrem key count value
|–> 若count > 0 表示从列表左侧移除count个跟value值相等的数据
|–> 若count < 0 表示从列表右侧移除count个跟value值相等的数据
|–> 若count = 0 表示从列表中移除所有跟value值相等的数据
|–> lpush list02 a a b c d a d e ==> e d a d c b a a
|–> lrem list02 3 a ==> e d d c b
i)截取指定列表中指定下标区间的元素组成新的列表,并且赋值给key:ltrim key startIndex endIndex
lpush list04 1 2 3 4 5 结果:5 4 3 2 1
ltrim list04 1 3
lrange list04 0 -1 结果:4 3 2
j)将指定列表中指定下标的元素设置为指定值: lset key index value
lset list04 1 10
k)将value插入到指定列表中位于pivot元素之前/之后的位置: linsert key before/after pivot vlaue
linsert list04 before 10 50
linsert list04 after 10 60
4)redis对set类型数据的操作命令 单key-多无序value
|–>value之间没有顺序,并且不能重复
a)将一个或者多个元素添加到指定集合中:sadd key value [value value]
|–>sadd set01 a b c
b)获取指定集合中的所有元素:smembers key
|–>smembers set01 ==> a c b
c)判断指定元素在指定集合中是否存在:sismember key member
|–> sismember set01 f ==> 0 存在返回1,不存在返回0
d)获取指定集合的长度:scard key
|–>scard set01 ==> 3
e)移除指定集合一个或多个元素:srem key member [member member]
|–> srem set01 b d m ==> 1 不存在的元素会忽略,返回成功移除的个数
f)随机获取指定集合中的一个或者多个元素:srandmember key [count]
|–> count > 0 :随机获取的元素不重复
|–> count < 0 :随机获取的元素可能重复
|–> sadd set02 1 2 3 4 5 6 7 8
|–>srandmember set02 ==> 7 / 2 / 5
g)从指定集合中随机移除1个或者多个元素:spop key [count] 默认1
h)将指定集合中的指定元素移动到另一个元素:smove source dest member
|–> smove set01 set02 a ==> 将set01中的a元素移动到set02中 返回移动成功的个数
i)获取第一个集合中有、但是其他集合中都没有的元素,返回临时集合:sdiff key key [key key···]
j)获取所有指定集合中都有的元素组成,返回临时集合:sinter key key [key key···]
k)获取所有指定集合中所有的元素组成的大集合:sunion key key [key key····]
5)redis中有关hash类型数据的操作命令:单key:field-value field-value
|–> 例:studentzs:id-1001 name-zhangsan age-20
a)将一个或者多个field-value对设置到哈希表中:hset key field1 value1 [field2 value2 ····]
如果key和field都存在,再次赋值,value会把以前覆盖。
|—> hset stu1001 id 1001 name zhangsan age 20 score 80.5 ==> 4
b)获取指定哈希表中指定field中的value:hget key field
|–> hget stu1001 id ==> 1001
c)批量将多个field-value对设置到哈希表中:hmset key field1 value1 [field2 value2····]
|–> hmset stu1002 id 1002 name lisi age 21 ==> 3
d)批量获取指定哈希表中指定field中value:hmget key filed1 [field2 filed 3 ···]
e)获取指定key中的所有field和value:hgetall key
f)从指定哈希表中删除一个或多个field:hdel key field1 [field2 field3···]
g)获取指定哈希表中field中的个数:hlen key
h)判断指定哈希表中是否存在某一个field:hexists key field
i)获取指定哈希表中所有的field:hkeys key
j)获取指定哈希表中所有的value:hvals key
k)对指定哈希表中指定field值进行整数加法运算:hincrby key field int
|—> hincrby stu1001 age 5 ==> 25
l)对指定哈希表中指定field值进行浮点数加法运算:hincrbyfloat key field
|—> hincrbyfloat stu1001 score 10.2 ==> 90.7
m)将一个field-value对设置到哈希表中;当key field已经存在,设置取消:hsetnx key field value
6)redis对zset数据类型的操作命令:有序集合
每个元素都关联一个分数,redis根据分数进行自动排序
a)将一个或多个member及其score值加入到有序集合中:zadd key score member [score member···]
如果元素已经存在,则覆盖覆盖分数
|—> zadd zset01 20 z1 30 z2 50 z3 10 z4
b)获取指定有序集合指定下标区间的元素:zrange key start end [withscores]
|—> zrange zset 0 -1 ==> z4 z1 z2 z3
c)获取指定有序集合中指定分数闭区间的元素:zrangebyscore key min max [withscores]
d)删除指定有序集合中一个或多个元素 zrem key member [member member ···]
e)获取指定有序集合中所有元素的个数:zcard key
f)获取指定有序集合中分数在指定区间内的元素个数:zcount key min max
g)获取指定有序集合中指定元素的排名(从小到大,排名从0开始):zrank key member
h)获取指定有序集合中指定元素的分数:zscore key member
i)获取指定有序集合中指定元素的排名(从大到小,排名从0开始):zrevrank key member
12.redis的配置文件
1)redis配置文件中关于网络的配置
port:redis服务所使用的端口(默认6379)
bind:配置客户端连接redis服务时,所能使用的ip地址,默认可以使用redis服务所在主机上任何一个ip,都会配置一个ip,而且通常是一个真实的ip。
|–> redis-cli -h -p [shutdown]
tcp-keepalive:TCP连接保活策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,假如设置为60秒,则server端会每60秒向连接空闲的客户端发起一次ACK请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接。如果设置为0,则不会进行保活检测。
2)redis常规设置:
loglevel:日志级别,开发阶段可以设置成debug,生产阶段通常设置为notice或者warning.
logfile:指定日志文件名,如果不指定,Redis只进行标准输出。要保证日志文件所在的目录必须存在,文件可以不存在。还要在redis启动时指定所使用的配置文件,否则配置不起作用。
databases:配置Redis数据库的个数,默认是16个。
3)redis安全配置
requirepass:配置Redis的访问密码。默认不配置密码,即访问不需要密码验证。此配置项需要在protected-mode=yes时起作用。一旦使用了密码验证,客户端连接服务器,必须输密码:redis-cli -h ip -p 6379 -a pwd
4)redis的持久化
redis是内存数据库,redis持久化到磁盘中后,每次redis启动服务时,把磁盘中的数据再次加载到内存中。redis提供了持久化功能——RDB和AOF(Append Only File)。
RDB策略:
在指定时间间隔内,redis服务执行指定次数的写操作,会自动触发一次持久化操作.
1、save <seconds> <changes>:配置复合的快照触发条件,即Redis 在seconds秒内key改变changes次,Redis把快照内的数据保存到磁盘中一次。默认的策略是:
1分钟内改变了1万次
或者5分钟内改变了10次
或者15分钟内改变了1次
如果要禁用Redis的持久化功能,则把所有的save配置都注释掉。
2、stop-writes-on-bgsave-error:当bgsave快照操作出错时停止写数据到磁盘,这样能保证内存数据和磁盘数据的一致性,但如果不在乎这种一致性,要在bgsave快照操作出错时继续写操作,这里需要配置为no。
3、rdbcompression:设置对于存储到磁盘中的快照是否进行压缩,设置为yes时,Redis会采用LZF算法进行压缩;如果不想消耗CPU进行压缩的话,可以设置为no,关闭此功能。
4、rdbchecksum:在存储快照以后,还可以让Redis使用CRC64算法来进行数据校验,但这样会消耗一定的性能,如果系统比较在意性能的提升,可以设置为no,关闭此功能。
5、dbfilename:Redis持久化数据生成的文件名,默认是dump.rdb,也可以自己配置。
6、dir:Redis持久化数据生成文件保存的目录,默认是./即redis的启动目录,也可以自己配置。
AOF策略:采用操作日志来记录进行每一次写操作
1、appendonly:配置是否开启AOF,yes表示开启,no表示关闭。默认是no。
2、appendfilename:AOF保存文件名
3、appendfsync:AOF异步持久化策略
always:同步持久化,每次发生数据变化会立刻写入到磁盘中。性能较差但数据完整性比较好(慢,安全)
everysec:出厂默认推荐,每秒异步记录一次(默认值)
no:不即时同步,由操作系统决定何时同步。
4、no-appendfsync-on-rewrite:重写时是否可以运用appendsync,默认no,可以保证数据的安全性。
5、auto-aof-rewrite-percentage:设置重写的基准百分比
6、auto-aof-rewrite-min-size:设置重写的基准值
13.redis的事务
事务:把一组数据库放在一起执行,保证操作原子性,要么同时成功,要么同时失败
redis的事务:允许把一组redis命令放在一起,把命令进行序列化,一起执行;保证部分原子性,一旦出错,分两种错误,1)严重错误,可以保证一致性。2)一般错误,哪一条错了,只影响错误语句,不影响其它语句。
1)multi:用来标记一个事务的开始
multi
set k1 k1
set k2 k2
2)exec:用来执行事务队列的所有命令
3)redis的事务只能保证部分原子性
a)如果一组命令,在压入队列时已经报错,则本事务所有命令都不执行,能够保证原子性
例:multi seta k1 1 或者 set k1 exec
b)如果一组命令,在压入队列时正常,在执行事务队列命令发生错误,则只影响发生错误的命令,其他不影响。
例:multi inc k1 set k3 12 exec
4)discard:清除所有压入队列的命令,并且结束整个事务。mutli set k4 4 set k5 5 discard
5)watch:监控某一个键,当事务在执行过程中,此键的值发生改变,则放弃语句;否则,执行语句。
|–> 例:在银行中,两个账户进行同时交互。保证金额的一致性。使用乐观锁,乐观锁提供一个version版本号,版本号一致才执行语句,不一致不执行。监控version值是否变化,再执行语句。
set balance 100
set balance2 200
set version 1
watch version
multi
incrby balance 50
decrby balance2 50
exec
6)unwatch:放弃监控所有的键
redis事务小结:
1、单独的隔离操作:事务中的所有命令都会序列化、顺序地执行。事务在执行过程中,不会被其它客户端发来的命令请求所打断,除非使用watch命令监控某些键。
2、不保证事务的原子性:redis同一个事务中如果一条命令执行失败,其后的命令仍然可能会被执行,redis的事务没有回滚。Redis已经在系统内部进行功能简化,这样可以确保更快的运行速度,因为Redis不需要事务回滚的能力。
14.redis.消息的发布与订阅:
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。消息发布者在频道发布消息,所有订阅者都能看到
1)subscribe:订阅一个或多个频道
|–>subscribe k1 k2 k3
2)publish:将消息发布到指定频道
|–> publish k1 hello
15.redis的主从复制 主少从多、主写从读、读写分离、主写同步复制到从
主机数据更新后根据配置和策略,自动同步到从机的master/slave机制,Master以写为主,Slave以读为主。
搭建一主二从集群:一个redis服务一台linux机器
1)搭建三台redis服务:(一台redis模拟三台redis服务,修改port)
提供三份修改配置文件:redis6379.conf redis6380.conf redis6381.conf
修改:port 6379
bind 127.0.0.1
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dbfilename dump6379.rdb
启动:redis-server redis6379.cong &
redis-server redis6380.cong &
redis-server redis6381.cong &
2)客户端连接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
3)查看三台机器在集群的主从信息:info replication 默认所有redis服务都是主机(能写能读)
4)先在6379进行写操作:set k1 v1 三台服务互相独立,互不影响
5)设置主从关系:设从不设主
在6380执行:slaveof 127.0.0.1 6379
在6381执行:slaveof 127.0.0.1 6379
6)全量复制:一旦主从关系确定,会自动把主库已有的数据同步复制到从库
7)增量复制:主库写数据会自动复制到从库
8)主机宕机、从机原地待命,数据不在更新
关闭6379服务 redis-cli -h 127.0.0.1 -p 6379 shutdown
查看6380 6381的主从关系
9)主机恢复、一切恢复正常:重启redis服务
10)从机宕机,主机少一个从机,其他从机不变
11)从机恢复:重启从机后,恢复成主机,再次设主从关系。slaveof -h -p
12)从机上位:
a)主机宕机、从机原地待命。
b)从机断开原来主从关系变为主机:slaveof no one
c)重新设置其他的从机的主从关系:slaveof -h -p
小结:一台主机可配置多态从机,一台从机也可配置多台从机,形成庞大的集群。
减轻一台主机压力,但是增加了服务器的延迟时间
16、redis哨兵模式:主机宕机、从机自动上位
哨兵模式原理
从机上位的自动版。Redis提供了哨兵的命令,哨兵命令是一个独立的进程,哨兵通过发送命令,来监控主从服务器的运行状态,如果检测到master故障了根据投票数自动将某一个slave转换master,然后通过消息订阅模式通知其它slave,让它们切换主机。然而,一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多哨兵进行监控。
1)设置一主二从集群环境
2)提供一个哨兵配置文件 端口26379
在redis安装目录创建配置文件:redis_sentinel.conf
sentinel monitor dc-redis 127.0.0.1 6379 1(票数)
3)启动哨兵服务:redis-sentinel redis_sentinel.conf
主机宕机,自动投票大的从机上位。宕机主机恢复,自动从属于新的主机
小结:
1 查看主从复制关系命令:info replication
2 设置主从关系命令:slaveof 主机ip 主机port
3 开启哨兵模式命令:./redis-sentinel sentinel.conf
4 主从复制原则:开始是全量复制,之后是增量复制
5 哨兵模式三大任务:监控,提醒,自动故障迁移
17.Jedis
直连
//1.生成一个jedis对象,这个对象负责和指定Redis节点进行通信Jedis jedis = new Jedis("119.23.226.29", 6379);//带密码需要执行认证方法//jedis.auth("123456");//2.jedis执行set操作jedis.set("hello", "world");//3.jedis执行get操作,value="world"String value = jedis.get("hello");System.out.println(jedis.ping()) //PONG
开6379端口命令
firewall-cmd --zone=public --add-port=6379/tcp --permanent
重启防火墙
systemctl restart firewalld.service
查看端口信息
firewall-cmd --list-ports
字符串
// 1.string
//输出结果: OK
jedis.set("hello", "world");
//输出结果: world
jedis.get("hello");
//输出结果:1
jedis.incr("counter");
哈希
// 2.hash
jedis.hset("myhash", "f1", "v1");
jedis.hset("myhash", "f2", "v2");
//输出结果 : {f1=v1, f2=v2}
jedis.hgetAll("myhash");
列表
// 4.set
jedis.sadd(" myset", "a");
jedis.sadd(" myset", "b");
jedis.sadd(" myset", "a");
//输出结果 : [b, a]
jedis.smembers("myset");
集合
// 4.set
jedis.sadd(" myset", "a");
jedis.sadd(" myset", "b");
jedis.sadd(" myset", "a");
//输出结果 : [b, a]
jedis.smembers("myset");
有序集合
// 5.zset
jedis.zadd("myzset", 99, "tom");
jedis.zadd("myzset", 66, "peter");
jedis.zadd("myzset", 33, "james");
//输出结果 : [[["james"],33.0], [["peter"],66.0], [["tom"],99.0]]
jedis.zrangeWithScores("myzset", 0, -1);
Redis可视化工具 Redis Desktop Manager
github地址: Releases · lework/RedisDesktopManager-Windows · GitHub