Redis--->是非关系型数据库(也称缓存数据库),是一种NoSQL数据库
存放5种数据类型 String key-value形式
另外list,set,zset,hash
另外两种不常用的:bitmap(位图类型),geo(地理位置类型),另外Redis5.0新增 stream类型
相对来说Redis适合存放少数据量的数据,如果需要存放大量数据到内存,推荐MongoDB,HBase.
是一个用C语言编写的开源的基于内存运行并支持持久化,高性能的NoSQL数据库.Redis种的数据大部分时间都是存储内存中,适合存储频繁访问,数据量娇小的数据.
特点:
1、支持数据持久化
Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
2、支持多种数据结构
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
3、支持数据备份
Redis支持数据的备份,即master-slave模式的数据备份。
Linux上安装Redis
官网:https://redis.io 选择下载相应版本

![]()

这目录不创建也行,多余
解压到该目录中 tar -zxvf redis-5.0.2.tar.gz -C /usr/local/develop/redis

进入该目录

执行命令 make 就是编译src
该命令有可能出错,出错原因可以是cc命令没找到,是C语言编译程序,好比运行java程序需要jdk里的命令一样
如果出现错误 如下操作

或者

或者直接
yum -y install gcc
以前安装过,所以都OK


如果说第一次make 因为没有安装gcc导致报错,很可能安装好gcc之后 继续执行make命令再次报错,原因是第一次编译过了,只是没法执行, 这种情况 在该目录执行清理命令 make distclea 然后再次执行make命令
继续当前目录执行make install 其实不执行该命令也可以启动Redis了,但是每次都要去Redis的bin目录,make install命令执行后,会配置到环境变量中就是local/bin环境目录里,就是你在任何目录下面都可以执行Redis命令

进入 /usr/local/bin redis的命令全配置好了 可以在任何目录启动

启动方式:
1. 前台启动 redis-server(会占用终端命令页面)
2.后台启动 redis-server &(用后台启动)
3.启动redis服务时,指定配置文件:在redis安装目录下有个redis.conf用来修改Redis配置
如果你修改了该配置文件,启动要指定该配置文件,不然配置不生效
启动命令 redis-server redis.conf &(指定配置文件并在后台启动)
如下图 可通过命令 vim redis.conf修改配置



回车一下

管道查一下
ps -ef|grep redis

关闭方式:
①使用redis客户端关闭,向服务器发出关闭命令
任意目录下执行 指令redis-cli shutdown
推荐使用这种方式, redis先完成数据操作,然后再关闭
②kill pid 或者 kill -9 pid
这种不会考虑当前应用是否有数据正在执行操作,直接就关闭应用。
先使用 ps -ef | grep redis 查出进程号,在使用 kill pid


Hello Redis
Redis客户端
Redis客户端是一个程序,通过网络连接到Redis服务器,从而实现跟 Redis服务器的交互。
Redis客户端发送命令,同时显示Redis服务器的处理结果。
redis-cli(Redis Command Line Interface)是Redis自带的基于命令行的Redis客户端,用于与服务端交互,我们可以使用该客户端来执行redis的各种命令。
redis的客户端:用来连接redis服务,向redis服务器发送命令,并且显示redis服务处理结果。
redis-cli:是redis自带的客户端,使用命令redis-cli就可以启动redis的客户端程序。
redis-cli:默认连接127.0.0.1(本机)的6379端口上的redis服务
redis-cli -p 端口号:连接127.0.0.1(本机)的指定端口上的redis服务 比如Redis集群指定端口号
redis-cli -h ip地址 -p 端口:连接指定ip主机上的指定端口的redis服务 比如Redis集群指定端口号
如果redis客户端有中文,使用redis-cli -h ip地址 -p 端口 --raw命令连接redis可以正常显示中文
例如:我在远端启动Redis服务

本机下载个Window版Redis里面有客户端

这样就连接上了
如果想在远端打开客户端,因已配置了redis全局环境命令
可任意目录执行
redis-cli -p 6379
这里有个报错 set的时候提示

查了下,需要将redis.conf文件修改下

![]()
........
改回yes,空了再弄
先远程启动客户端耍耍
默认情况不需要密码
可以对Redis数据库进行增删改查
退出客户端 exit 或者quit

Redis基本知识
一些基础命令
1.redis-benchmark 用来测试redis性能 模拟处理10W个请求

2.Redis沟通命令,查看状态
ping 返回PONG
解释:输入ping,redis给我们返回PONG,表示redis服务运行正常

3.查看redis服务器的统计信息:info server和info 进入redis-cli客户端输入该命令
语法:info [section]
作用:以一种易于解释且易于阅读的格式,返回关于 Redis 服务器的各种信息和统计数值。section 用来返回指定部分的统计信息。 section的值:server , clients ,memory等等。不加section 返回全部统计信息
返回值:指定section的统计信息或全部信息
4.redis默认使用16个库
Redis默认使用16个库,从0到15。 对数据库个数的修改,在redis.conf文件中databases 16,理论上可以配置无限多个

Redis中的数据库实例只能由redis服务来创建和维护,开发人员不能修改和自行创建数据库实例
5.切换库命令:select db
默认使用第0个,如果要使用其他数据库,命令是 select index

6.查看当前数据库中key的数目:dbsize
Redis 0号库默认放着4个键值对

7.查看当前数据库中有哪些key:keys *

8.清空当前库:flushdb

9.清空所有数据库:flushall
10.config get * 获得redis的所有配置值
语法:config get parameter
作用:获取运行中Redis服务器的配置参数, 获取全部配置可以使用*。参数信息来自redis.conf 文件的内容。
例1:获取数据库个数 config get databases

config get port

flushall 清空所有数据库
redis英文版命令大全:Commands | Redis
redis中文版命令大全:Redis 命令参考 — Redis 命令参考
Redis常用5种数据结构
A.字符串类型 string
字符串类型是Redis中最基本的数据结构,它能存储任何类型的数据,包括二进制数
据,序列化后的数据,JSON化的对象甚至是一张图片。最大512M。

B.列表类型 list
Redis列表是简单的字符串列表,按照插入顺序排序,元素可以重复。你可以添加一个元素到列表的头部(左边)或者尾部(右边),底层是个链表结构。

C.集合类型 set
Redis的Set是string类型的无序无重复集合。

D.哈希类型 hash
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。

E.有序集合类型 zset (sorted set)
Redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员。
不同的是zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。

Redis的常用操作命令
1.key的操作命令
1.1)keys的操作命令
语法:keys pattern
作用:查找所有符合模式pattern的key. pattern可以使用通配符。
通配符:
keys wo[]d

语法:exists key [key…]
作用:判断key是否存在
返回值:整数,存在key返回1,其他返回0。使用多个key,返回存在的key的数量。

语法:ttl key
作用:查看key的剩余生存时间(ttl: time to live),以秒为单位。
返回值:

1.查询数据库中的key
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
2.判断key在数据库中是否存在:exists key 如果存在则返回1,如果不存在则返回0
exists k1:判断k1是否存在 存在返回1 不存在返回0
exist k1 k2 k3:判断k1 k2 k3是否存在 返回值是存在的key的数量
3.move移动指定key到指定的数据库实例,原来库里的该数据删除
move k1 1:将key为k1的数据移动到1号库
4.ttl查看指定key的剩余生存时间,返回-1表示没有设置key的生存时间,永不过期.返回-2,表示key不存在,时间以秒为单位
ttl k1:查看key为k1的key的剩余生存时间
5.expire设置key的生存时间,以秒为单位,超过时间key自动删除,返回1表示设置成功,返回0表示其他情况
expire k1 20:设置key为k1的该条数据生存时间为20秒,20秒后自动删除
6.type查看key存储值的数据类型
返回值none(key不存在),String(字符串),list(列表),set(集合),zset(有序集),hash(哈希表)
7.rename key newkey.将key改名为newkey. 当key和newkey相同,或者key不存在时,返回一个错误.当newkey已经存在,将会把旧值覆盖
rename k1 k11:将key为k1的数据改名为key为k11
8.del删除存在的key,如果key不存在,忽略,返回值为删除的key的数量
del k1:删除key为k1的该条数据
del k1 k2:删除key为k1还有k2的两条数据
--------------------------------------------------------------------------------------------------------------------
有关String类型数据的操作命令,单key 单value(数值,boolean在redis中都是以字符串形式存储)
1.将String类型的数据保存到redis中:set
set zs zhangsan:设置key为zs,value为zhangsan的字符串到redis
set age 100:设置key为age,value为100的字符串到redis
set age 200:设置key为age,value为200的字符串到redis,如果key已经存在会把以前的value覆盖
2.get获取String类型的数据
get zs:获取key为zs的value值
3.append追加字符串,返回值:返回追加之后字符串长度,key如果不存在,相当于set
append age 123:将数据库原有key为age的value值,比如说200追加为200123
4.strlen获取key对应value值字符串的长度
strlen age:查看key为age对应value字符串的长度
5.incr对表示数值的字符串进行+1运算,返回+1之后的数据值,如果key不存在,首先设置一个key,value初始化为0,然后进行incr运算+1.如果value值不是数值的话,报错.value必须是数值
incr age:将key为age的value值进行+1运算
6.decr对表示数值的字符串进行-1运算,返回-1之后的数据值,如果key不存在,首先设置一个key,value初始化为0,然后进行incr运算-1.如果value值不是数值的话,报错.value必须是数值
incr age:将key为age的value值进行-1运算
7.将字符串数值进行off(偏移量)set运算: incrby key offset(加几)
incrby age 100:将key为age的value值进行+100运算,offset随意多少,100就是那个offset(偏移量).如果value值不是数值的话,报错.value必须是数值.返回加100之后的数据值
8.将字符串数值进行off(偏移量)set运算: decrby key offset(减几)
decrby age 69:将key为age的value值进行-69运算,offset随意多少,69就是那个offset(偏移量).如果value值不是数值的话,报错.value必须是数值.返回减69之后的数据值
9.获取(截取)字符串中的子字符串:getrange key startIndex endIndex.(下标从0开始),不影响原数据
getrange age 1 5:比如说age的value是1234567 那么截取到的值就是23456
getrange name 1 5:比如说age的value是zhangsang 那么截取到的值就是hangs
getrange name 1 20:比如说age的value是zhangsang 那么截取到的值就是hangsang
getrange name 1 -1:比如说age的value是zhangsang 那么截取到的值就是hangsang
getrange name 1 -2:比如说age的value是zhangsang 那么截取到的值就是hangsan
getrange name 1 -3:比如说age的value是zhangsang 那么截取到的值就是hangsa
getrange name 0 -1:比如说age的value是zhangsang 那么截取到的值就是zhangsang
10.覆盖字符串setrange key starIndex value
setrange name 1 x:比如说age的value是zhangsan 从下标1开始覆盖 覆盖的值为x,返回覆盖之后的长度 那么value就变成zxangsan
setrange name 1 xqwertyui:比如说age的value是zhangsan 从下标1开始覆盖 覆盖的值为xqwertyui,返回覆盖之后的长度 那么value就变成zxqwertyui
11.设置字符串同时什么最大生命周期setex
setex name 20 zhangsan:设置key为name,value为zhangsan,生命周期为20秒
12.设置字符串但如果key已经存在,则放弃设置,不会盲目覆盖setnx
setnx name zhangsan:设置key为name,value为zhangsan到数据库,如果key不存在,则设置,如果key不存在则放弃设置
13.批量设置数据到数据库(好比批量插入)mset key1 value1 key2 value2 key3 value3
mset name zhangsan age 20 gender 男:如果key存在,会被覆盖,中文如图

14.批量设置数据到数据库(好比批量插入)msetnx key1 value1 key2 value2 key3 value3
msetnx name zhangsan age 20 gender 男:只有当所有key都不存在,才成功,只要有一个key存在,全失败
---------------------------------------------------------------
有关List类型数据的操作命令 单key 多value 而且多个有序的value 每个value都是字符串值 下标从0开始 最后一位可以按正常从0开始的最后一位下标表示,也可以用-1表示 最后第二位-2
插入数据或者查数据都要靠下标
1.将一个或者多个值一次插入到列表.lpush key value 或者lpush key value1 value2 value3.返回插入的value个数.lpush插入key的value顺序是 value3 value2 value1
lpush phone 88588888 13998905688 999:插入key为phone value分别为999 13998905688 88588888有序列表
lpush phone 666 888:那么value值顺序为
888 666 999 13998905688 88588888
2.查看(获取)指定列表(list)中指定下标区间的元素:lrange key startIndex endIndex
lrange phone 0 1:获取key为phone的list中下标为0到下标为1的元素(含头也含尾) 返回888 666
lrange phone 0 2:获取key为phone的list中下标为0到下标为2的元素(含头也含尾) 返回888 666 999
lrange phone 1 -2:获取key为phone的list中下标为1到倒数第2个元素(含头也含尾) 返回666 999 13998905688
lrange phone 0 -1:获取key为phone的list中下标为0到最后个元素(含头也含尾) 返回888 666 999 13998905688 88588888
3.将一个或者多个值一次插入到列表.rpush key value 或者rpush key value1 value2 value3.返回插入的value个数.rpush插入key的value顺序是 value1 value2 value3
rpush list01 hehe haha deidei:插入key为phone value分别为hehe haha deidei有序列表
rpush list01 a b c:那么顺序就变成hehe haha deidei a b c
如果这里我在lpush list01 e f:那么顺序就变成e f hehe haha deidei a b c
4.lpop从指定列表中移除并且返回从左侧下标0开始开始的元素:lpop key
lpop list01:删除key为list01从左侧开始第一个元素,即下标为0的元素
5.从指定列表移除并且返回表尾元素:rpop key,返回被删元素
rpop list01:移除key为list01列表里表尾最后一个元素
6.查看获取指定列表中指定下标的元素:lindex key index
lindex list01 0:获取查看key为list01里指定下标0的元素
7.获取指定列表的长度:llen key
llen list01:获取key为list01里value的个数
8.根据count值移除(删除)列表中跟value相等的数据:lrem key count value.返回删除的个数
如果count大于0:从列表左侧开始移除count个跟value相等的数据
如果count小于0:从列表右侧开始移除count个跟value相等的数据
如果count等于0:从列表中移除所有跟value相等的数据
比如list01中的value是 a f f b c a d e a f f
那么lrem list01 2 f:表示删除key为list01从左侧开始删除2个value值为f的value,删除后a b c a d e a f f.返回删除的个数
lrem list01 -2 f:表示删除key为list01从右侧开始删除2个value值为f的value,删除后剩下a b c a d e a
lrem list01 0 a:表示删除key为list01所有value值为a的value,删除后剩下b c d e
-----------------------------------------------------------------------------------
Redis中有关set类型数据的操作命令:单key-多value(value不能重复)且无序,一个key对应多个value
因为无序,那么不用像list一样考虑左侧插入还是右侧插入,反正就是插入
Redis的Set是String类型的无需不重复集合.
1.将一个或多个元素添加到指定集合中:sadd key value或者sadd key value1 value2 value3,如果后面的value相同,以第一个为准,重复加入的不成功,返回成功加入的元素的个数
sadd set01 a b c:将a b c三个value插入到指定的key为set01的set集合,如果value重复(已存在该value)则忽略
2.获取指定集合中所有的元素:smembers key
smembers set01:返回key为set01的集合中的所有元素
3.判断指定元素在指定集合中是否存在:sismember key member,member指元素value,如果存在返回1,不存在返回0
sismember set01 f:判断key为set01的集合里是否含有元素f,存在返回1,不存在返回0
4.获取指定集合的长度即某key的集合元素的总个数:scard key
scard set01:获取key为set01的元素个数
5.移除指定集合中一个或多个元素:srem key value或者srem key value1 value2 value3,集合中不存在的元素会被忽略,返回成功移除的个数
srem set c d m:移除set01集合中value为 c d m的元素,如果该value在该集合中没有,则忽略,返回成功移除的个数
6.随机获取指定集合中的一个元素或多个元素:(抽奖) srandmember key(一个)
srandmember key count
如果count大于0,随机从该集合中获取count个元素,而且count个元素都不会重复
如果count小于0,随机从该集合中获取count个元素,但是元素可能重复,可能不重复
比如我先往集合中放些数据sadd set02 1 2 3 4 5 6 7 8 9 10
然后再srandmember set02:随机从set02中获取一个值 常用于抽奖

7.从指定集合中随机移除一个或多个元素:spop key或spop ket 1或者spop key count,,返回被移除的元素值
spop key或spop key 1都是从指定集合随机移除一个元素,返回被移除的元素值
spop key count是从指定集合随机移除多个元素,返回被移除的元素值
8.集合和集合中将指定集合中的指定元素移动到另一个集合:smove source dest member,返回移动的个数
例如现在有set01和set02

将set01中的a移动到set02去
命令:smove set01 set02 a 这样set01少了个元素a set02里多了个元素a

9.集合与集合的交集,差集,并集
9.1)求差集sdiff key key或者sdiff key key key .....获取指定第一个集合中有,但是其他集合中都没有的元素组成的新集合,返回新集合的value
9.2)获取所有指定集合中都有的新集合,求交集(大家都有的):sinter key1 key2......,返回新集合的value
9.3)获取所有指定集合中,所有元素组成的大集合,求并集:sunion key1 key2......返回新集合的value
-------------------------------------------------------------------------------------------------
Redis中有关hash类型数据的操作命令:单key value是一个对象,对象里是属性名对应属性值
field-value
field-value.......
例如:key为student value为 id-1 name-zhangsan age-20
因此要创建hash,首先取个key名,然后是file(域)对应值,file(域)对应值......
学术些讲:Redis的hash是一个String类型的key和value的映射表,这里的value是一系列的键值对,hash特别适合用于存储对象.
hash类型的数据操作总的思想是通过key和field操作value,key是数据标识,field是域,value是我们感兴趣的业务数据.
1.将一个或者多个filed-value对设置到哈希表中:hset key filed value或者
hset key field1 value1 field2 value2.......返回成功插入的field-value的对数,如果key field已经存在会覆盖掉
hset studen01 id 1001 name zhangsan age 20
2.获取指定哈希表中指定field的值:hget key field,返回该field的值
hget student01 name:获取key为student01的哈希表中,field为name的值,返回该field的值
3.hmset用法和hset key field1 value1 field2 value2.......完全一样
4.批量获取指定哈希表中多个field的值:hmget key field1 field2 field3....,返回这些field的值
5.在不知道field的情况下,获取指定哈希表中所有的field-value:hgetall key

6.从指定哈希表中删除一个或者多个field:hdel key field或者hdel key field1 filed2.....
hdel studen01 id name:删除hash表中key为studen01的 filed为id和name的field-value对
7.指定哈希表中所有的field个数:hlen key,返回值是field-value的个数
hlen studen01
8.判断指定哈希表中是否存在某一个field:hexists key field.存在返回1,不存在返回0
9.获取哈希表中某key对应的所有field:hkeys key
10.获取哈希表中某key对应的所有value:hvals key
11.如果哈希表中某key对应的某field对应的value是个数值,可以对该数值进行加法运算(int只能是整数)
hincrby key field int
hincrby studen01 age 5:哈希表中对key为studen01 field为age的value值加5,返回加之后对应的整数
12.如果哈希表中某key对应的某field对应的value是个数值,可以对该数值进行加法运算(float是浮点数)
hincrbyfloat key field float
13.针对于第一个方法(第一种设置方式其实是很危险的),hsetnx key field value或hsetnx key field1 value1 field2 value2...
也是设置,但是当key field已经存在,则放弃设置.反之则设置成功
----------------------------------------------------------------------------------------------------------
Redis有序集合zset和集合set一样也是String类型元素的集合,且不允许重复的成员.
不同的是zset的每个元素都会关联一个分数(分数可以重复),Redis通过分数来为集合中的成员进行从小到大的排序.
Redis中有关zset类型数据的操作命令:zset是有序集合,对集合里每一个value对应一个分数,然后redis根据对应分数对集合进行排序(升序)
zset集合的每一个value必须关联分数
1.将一个或者多个member及其分数值放入一个有序集合:zadd key score member.如果元素已经存在分数会被覆盖
zadd zset01 100 z1 200 z2 300 z3
2.获取指定有序集合中指定下标区间的元素:zrange key startIndex endIndex
zrange zset01 0 -1:获取所有元素
zrange zset 0 1:获取z1 z2
zrange zset 0 -1 withscores:获取所有元素和所有元素的分数
3.获取指定有序集合中指定分数区间的元素:zrangebyscore key min max
zrangebyscore set01 100 300.查出来的元素包含分数100和300的
zrangebyscore set01 100 300 withscore:把value和分数都查出来
4.指定有序集合中一个或者多个元素:zrem key member或者zrem key value1 value2.....
zrem zset01 z1 z2
5.获取指定有序集合中所有元素的个数:zcard key
zcard zset01
6.获取指定有序集合中分数在指定区间内的元素个数:zcount key min max
zcount set01 100 400
7.获取指定有序集合中指定元素的排名(排名从0开始):zrank key value
zrank zset01 z3:返回从0开始的下标
8.获取指定有序集合中指定元素的分数:zscore key value
zscore zset01 z4:返回z4的分数
9.zrevrank key value获取指定有序集合中指定元素的排名(反向排名,按照分数从大到小的排名)
返回从大到小的(最后一位下标为0)下标排名
---------------------------------------------------------------------------------------
Redis的配置文件:在redis根目录下提供redis.conf配置文件,可以配置一些redis服务端运行时的一些参数,如果不适用配置文件,那么redis会按照默认的参数运行,运行命令是redis-server &
如果对redis.conf有修改,比如端口号,需要指定指定该配置文件,比如在redis根目录下
则启动命令redis-server redis.conf &来启动redis
redis-cli是客户端启动命令
redis默认启动端口是6379,如果改成了6380且根据配置配件改动启动如:redis-server redis.conf &
在同一台机器上的话,客户端连接命令为 redis-cli -p 6380
如果服务端和客户端在不同IP(不同主机上)
客户端要去连接 redis-cli -h xx.xx.xx.xxx -p 6380
关闭服务命令
redis-cli -h xx.xx.xx.xxx -p 6380 shutdown
退出客户端 exit quit
port:指定redis服务所使用的端口,默认6379
bind:配置客户端连接redis服务时,所能使用的ip地址,默认可以redis服务所在主机上任何一个ip都可以,真实情况下,一般都会配置一个ip,而且通常是一个真实IP

应该是服务端redis配置没有指定ip的原因
具体连接方式查看本地客户端连接阿里云Redis服务器_fhrui的博客-CSDN博客
关于tcp-keepalive:TCP连接保活策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,假如设置为60秒,则Redis服务端每60秒向连接空闲的客户端发起一次ACK(虚拟)请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接.如果设置为0,则不会进行保活检测.毕竟数据库的同时连接数量是有限的.
好比问你活着么,客户端答一句还活着,那就这么苟活着吧,如果一直没反应,即使你还活着,我当你挂了

Redis的常规配置
1.loglevel:日志级别,开发阶段可以设置成debug,生产阶段通常设置成notice(输出报错异常信息)或者warning.
2.logfile:默认是没有配置的.指定日志文件名,如果不指定,Redis只进行标准输出.要保证日志文件所在的目录必须存在,文件可以不存在.还要在redis启动时指定所使用的配置文件就是redis.conf.否则配置不起作用.
3.databases:配置Redis数据库的个数,默认16个
演示一下:在redis根目录下 vim redis.conf

没有配置,默认将日志全打在控制台,但是我们经常后台启动,因此会看不到日志信息
配置一下



Redis的安全配置:
1.requirepass:配置Redis的访问密码.默认不配置密码.即访问不需要密码验证.
此配置项需要在protected-mode=yes时起作用.使用密码登录:
redis-cli -h xx.xx.xx.xxx -h 6379 -a pwd
protected-mode yes Redis会做权限密码工作
protected-mode yes 一旦设置了密码验证,客户端连接redis服务时,必须使用密码连接
redis-cli -h xx.xx.xx.xxx -p port -a pwd
Redis不考虑事务的原子性
Redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,Redis数据库里的所有数据将全部丢失.为解决这个问题,redis提供了持久化功能--RDB和AOF(Append Only File)
RDB是Redis默认的持久化方案.在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中.即在指定目录下生成一个dump.rdb文件.Redis重启后会通过dump.rdb文件来恢复数据
RDB原理:
Redis会复制一个与当前进程一样的进程.新进程的所有数据(变量,环境变量,程序计数器)等值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,来进行持久化.
整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能
简单说就是:在指定时间间隔内,Redis服务执行指定次数的写操作,会自动触发一次持久化操作
Redis的RDB配置
1.save
Redis把快照内的数据保存到磁盘中一次.默认的策略是:
1分钟内改变了1万次 save 60 10000
或5分钟内改变了10次 save 300 10
或15分钟内改变了1次 save 900 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的启动目录,也可以自己配置
总结:save
dbfilename:配置redis RDB持久化数据存储的文件
dir:配置Redis RDB持久化文件所在目录
Redis AOF配置(弥补RDB的不足):采用操作日志来记录进行每一次写操作
简单来说AOF就是redis每次服务启动时,都会将日志文件里的所有写操作重新执行一遍,以免丢失数据,redis默认不开启,开启后降低效率
1.appendonly:配置是否开启AOF,yes表示开启,no表示关闭.默认是no,关闭
2.appendfilename:AOF保存文件名
3.appendfsync:AOF异步持久化策略
always:同步持久化,每次发生数据变化,会立刻写入到磁盘中,性能较差,但数据完整性比较好(慢,但是安全)
everysec:出厂默认推荐,每秒异步记录一次(默认值)
no:不即时同步,由操作系统决定何时同步
4.no-appendfsync-on-rewrite:重写时是否可以运用appendsync,默认no,可以保证数据的安全性
4.auto-aof-rewrite-percentage:设置重写的基准百分比
5.auto-aof-rewrite-min-size:设置重写的基准值
举例,一般数据字典里的数据,服务启动时,会从关系数据库里查出来,放到缓存数据库中,那么以后字典表数据就直接从redis里取.即使redis里丢失,但是数据在关系型数据库mysql里有备份,一般来说,redis中存的数据,在关系型数据库里都有,因为相对关系型数据库里的数据查询效率低,所以先查出来放到redis里面,如果有数据放到mysql里,同时往redis里也放一份,这样redis就不需要再备份了,这种情况下可以把默认开启的RDB策略关闭.因为mysql里本身就有备份了
---------------------------------------------------------------------------------------------------------
只要是数据库,无论关系型数据库还是非关系型数据库,都会有事务的控制.
原子性、一致性、隔离性、持久性
原子性:事务中的操作为一个整体,要么都做,要么都不做.即一旦事务出错,就回滚事务
隔离性:一个事务的执行不能被其他事务干扰。即一个事物内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事物之间不能互相干扰
持久性:指一个事物一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
一致性::执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。
事务:把一组数据库操作放在一起执行,来保证操作的原子性
原子性:一组操作要么同时成功,要么同时失败(注意redis不能保证全部事务的原子性)
Redis的事务:允许把一组redis命令放在一起执行,但不强调原子性.把命令进行序列化,然后一起执行,保证部分原子性.(如果是严重的错误,可以保证原子性,如果一般的错误,不能保证)
redis事务命令:
1)multi:用来标记一个事务的开始(开启)
事务执行演示,比如说要设置
set k1 v1 set k2 v2
因为现在redis服务器已经设置了密码,如果是本机客户端登录命令 redis-cli -a pwd
如果是登录命令是redis-cli -p ip -h port -a pwd
2)exec:用来执行事务队列中所有的命令
3)redis的事务只能保证部分原子性
a)如果一组命令中,在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,此种情况是可以保证事务原子性的
b)如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,不会影响其他命令执行,不能够保证事务的原子性.

保证事务原子性演示
比如 set k3 v3;set k4 v4再压入set k5 v5时候写错了 写成了setk5

c)discard:清除所有已经压入队列中的命令,并且结束整个事务.
比如说lmulti . set k5 v5 . set k6 v6. discard . 然后再exec会提示事务已结束 就是啥都没干
redis的事务,开启事务后,所有的命令都会先被压入队列
d)watch:监控某一个键,当事务在执行过程中,此键代码的值发生变化,则本事务放弃执行,否则正常执行,相当于乐观锁里的version
演示

最后执行事务,是不成功的,原因:监控的key的值被另外一个客户端改了

e)unwatch:放弃监控所有的键
watch version
unwatch
multi
decrby balance 50
incrby balance2 50
exec
-------------------------------------------------------------------------------------------------------
Redis客户端订阅频道,消息的发布者(也是客户端)忘频道上发布消息,所有订阅此频道的客户端都能够接受到消息
具体实践就两个命令
1)subscribe:订阅一个或多个频道的消息
subscrebe ch1 ch2 ch3 :订阅了三个频道
2)publish:将消息发布到指定频道
publish ch1 hello :

3)psubscribe:也可以订阅一个或多个频道的消息,频道名支持通配符
psubscribe news.* 频道名还有new.的任何频道都可以收到
其实消息的发布与订阅,用的并不多,也不会去用Redis的消息发布与订阅.因为即使用的话,一般不用redis的消息发布与订阅
而是用消息通信的中间件,包括ActiveMQ RabbitMQ 专门用来消息的通信与发布的
--------------------------------------------------------------------------------------------------------
主写从读,一台redis负责写,另外几台redis负责读,读写分离,主写后同步到从库
搭建一个 一主二从的redis集群
1)搭建3台redis服务 服务器多的话,那就弄3台服务器
这里就按不同端口,来启动3个redis服务 这种方式不太好

因为三台服务的配置有可能不同,这样 全部停了 分别复制三个配置文件
比如redis6379.conf redis6380.conf redis.6381.conf
把几个进程杀了

复制几个redis.conf
命令:cp redis.conf redis6379.conf
每个配置文件要改的地方:
port 8379
pidfile /var/run/redis_6379.pid
logfile "redislog6379.log"
dbfilename dump6379.rdb
这四个地方




当然ip绑定的是你的每台服务器的真实ip 这里没有这么多服务器 ip直接注释掉

对应redis6380.conf 也需要改这几个地方

对应redis6381.conf port 6381 pidfile /var/run/redis_6381.pid logfile "redislog6381.log" dbfilename dump6381.rdb
然后分别按各自的配置文件 启动3个redis服务

2)查看三台服务在集群中的主从角色
先用三个客户端去连接 连接命令 redis-cli -h ip -p port -a pwd
连了半天 除了6379其他两个连不上 才想起来安全策略 6380和6381没开

3)查看三台redis服务在集群中的主从角色 默认所有redis服务都是master 主机都可以写和读,都没有从机
info replication

4)先在6379进行写操作 三台redis服务相互独立 互不影响 6379里写入数据和6380和6381没有关系
5)设置主从关系(设从不设主):让6379当主机 6380和6381当从机 需要做的事:设从不设主(6379不变 去改变6380和6381)
设置6380和6381
slaveof ip port 这样 6379就变主机 而6380和6381就变成从机了


master_link_status:正确应该是up,正在激活 现在却一直是down
后来发现原因:是因为我每个配置文件里都有密码的原因
修改从数据库的配置文件 就是redis6380和redis6381.conf 记得两个从库都要加上去

这样就ok了 重新启动三个reids服务 启动就有了主从关系了 客户端info replication查看、
也不需要slaveof ip port



但是确实主从关系后发现,不能再往从库写入数据了
也就是说主从关系确定后 主库用来专门负责写 而从库只能读 主写从读

6)全量复制:一旦主从关系确定,会自动把主机上已有的数据同步复制到从库
7)增量复制:往6379上添加数据:主库写入数据会自动同步到从库.
8)主从关系确定后:主从复制,主写从读,读写分离,伤心死我了
关于服务器防火墙端口,像阿里云服务器,可以通过安全策略打开
比如物理服务器开启防火墙端口

注意:从机只能隶属于1个主机 如果有多台主机,还有个节点的概念......
支持小集群搭建完成
---------------------------------------------------------------------------------------------
下面演示主从复制,读写分离后一些出错情况及如何解决
如果从库宕机了,没关系,反正还有一台 而且自己试过了 从库重启之后会自动从主机那边复制一份过来
9)主机宕机,从机原地待命
exit退出客户端 redis-cli -h ip -p port -a pwd shutdown 关闭6379端口的redis服务
进入从机info replication 发现master_link_status:down
当主机宕机之后,从库的角色还是从库,但是里面的数据就不会再更新了
10)主机恢复: 一切恢复正常
重启6379服务 redis-server redis6379.conf
进入客户端info replication
还是主机,对应两个从机也没有改变
进入从机 info replication 发现master_link_status:up 激活了
11)从机宕机:主机少一个从机,其他从机不变
比如关闭6380服务 redis-cli -h 127.0.0.1 -p 6380 shutdown
查看6379的主从角色:还是主机,但是从机从两个变成了1个
查看6381的主从角色:还是从机,从属于6379,不受影响
12)从机恢复:从启后,数据自动从主机复制(主要是我在配置文件里 配置了主从关系) 如果没有在配置文件里写死主从关系 而是靠命令去匹配主从关系的话,重启后就变主机了 靠命令匹配主从关系
先进入客户端 然后slaveof xx.xx.xx.xxx port 只要变成了从机,就会从主机那边全量复制,增量复制功能自动完成
13)主机宕机,从机上位:
一般主机宕机,从机待命,前面已经演示过了
那么还有个配置,或者说命令:主机宕机,从机上位
如果没有在.conf文件里写死
比如6379断开了要6380上位,在6380客户端执行命令:slaveof no one 这样就当主机了,但是需要6381也配置一下,如果配置文件没有写死,那么就在6381客户端执行slaveof ip port,不好意思.没找到怎么配置,有没有这个配置不知道,其实就是后面要讲的哨兵模式
如果原来的主机恢复,虽然是主机,但是就没有从机了--->天堂变地狱,要么当从机,要么全部重新设置一遍
注意一个从机下面还可以有从机
如果配置文件里没有配置,记住几个命令: 进入客户端 比如 slaveof 127.0.0.1 6379 意思就是当6379的从机
slaveof no one:就是恢复自己主机身份,不做别人从机 info replication查看信息
小结:一台主机配置多台从机,一台从机还可以配置多太从机,从而形成庞大的集群结构.减轻主机压力.但是它真假了服务间的延迟时间.配置多太主机,需要节点.不知道
复制原理:
全量复制:slave(从机启动成功)启动成功连接到master(主机)后会发送一个sync指令,Master接到指令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave(从机),以完成一次完全同步,slave(从机)服务在接收到数据库文件数据后,将其存盘并加载到内存中.
只要是重新连接master,一次完全同步(全量复制)将被自动执行.
增量复制
Master将新的所有收集到的修改命令依次传给slave,完成同步
其实复制dump.rdb文件,且让redis.conf里配置相同的dump.rdb就可以全量复制redis数据
dump.rdb好比一个sql脚本.
Redis哨兵模式:主要为了解决redis主从复制中存在的一个问题,就是主机宕机,从机待命(不能再写数据进去),当然我们可以用命令来做,就是主机宕机,从机上位.还得配主机,还得配从机,但是这要靠敲命令,我们并不知道主机什么时候挂.
也就是说哨兵模式是为了解决主机宕机,从机待命,或者需要通过手动模式去解决主机宕机从机上位,但是谁都不知道什么时候主机会宕机的这个问题
哨兵模式:你将主机信息告诉我,我来监控主机,万一主机宕机了,我自动从从机分配主机(后台有程序监控主机)
用哨兵模式需要配置一个文件,这里我们不用它

我们用自己的,它里面有很多我们用不到的配置
在redis安装目录下创建文件redis_sentinel.conf
并编辑内容:sentinel monitor dc-redis 127.0.0.1 6379 1 表示监控主机的ip地址,port端口,得到哨兵的投票数(当哨兵投票数大于或者等于此数时切换主从关系)dc-redis就是该哨兵的名字
主机宕机了,它会去从机里找,根据一定算法投票,自动选一个当主机 最后一个1的原因是,总共我们这里就2个从机,2个从机说明只有两票 1的意思是 谁先得到1票 谁就当主机 即使多个从机 1是最快的
创建文件命令: touch redis_sentinel.conf

然后编辑:vim redis_sentinel.conf 保存

其实可以通过vim redis_sentinel.conf 编辑并且直接创建
启动哨兵服务:redis-sentinel redis_sentinel.conf
发现不行,原因是我配置了密码 用下面这种设置


因为我配置文件里都写死了 假如我关闭6379 看下 会不会自动分配主机
OK的即使配置里写死 检测到主机挂了 它也从从机里指定新的主机

80已经成功上位

此时,如果主机恢复,以前,如果主机恢复,会成为独立主机,没有从机,那么在哨兵模式下,会如何???
重启6379
此时原先主机恢复 却发现当了从机,这个是OK的 但是发现 master_link_status:down
这就有问题了,肯定是我哪里配置出问题 这个日后解决

原因找到了 是因为6379 一开始就是master 它的配置里面没有设置masterauth 密码 当它重启变成从机后不知道现有主机的密码 因此无论主机从机 都需要设置masterauth
重启后发现 6379不再是主机 而是6380也就是说,哨兵模式,只要记录了主机,它会改掉你配置里的主机,用它自己的redis-sentinel.conf记录 以它的记录为准
如果还想6379为主机 那么可以将redis_sentinel.conf重新配置
看,我只写了两句 它自动再改,再有主机宕机 还会改

小结:
1.查看主从复制关系命令:进入客户端 info replication
2.设置主从关系命令:slaveof 主机ip 主机port
3.开启哨兵模式命令:./redis-sentinel.conf
4.主从复制原则:开始是全量复制,之后是增量复制
5.哨兵模式三大任务:监控,提醒,自动故障迁移
缺点:
Redis的主从复制最大的缺点就是延迟,主机负责写,从机负责备份,这个过程是有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,从机器数量的增加也会使这个问题更加严重
-------------------------------------------------------------------------------------------------------------------
Jedis操作Redis
1.Jedis操作key
2.Jedis操作字符串String类型数据
3.Jedis操作列表list类型数据
4.Jedis操作哈希hash类型数据
5.Jedis操作集合set类型数据
6.Jedis操作有序集合zset类型数据
7.Jedis操作事务








重新整理下


因为这里我连的是集群的主库 写入后其他库里会主从复制

Jedis事务
