Redis
Redis简介
Redis是一种数据库。
数据库演变历程:单机数据库时代,Memcached时代,读写分离时代,分表分库时代(集群),nosql时代
nosql时代前的是关系型数据库时代
关系型数据库:Oracle,MySQL,DB2,SQLServer
NoSql(not only sql 不仅仅是sql),泛指非关系型数据库:不再采用关系数据模型,而是采用聚合数据结构存储数据
NoSql数据库:redis,mongoDB,HBase
Redis:Remote Dictionary Server(远程字典服务器),用C编写的高性能的基于内存运行并支持持久化的Nosql数据库。
redis中的数据大部分时间都是存储内存中的。所以Redis检索效率高,但不能存储太大数据。适合存储频繁访问,数据量小的数据。Redis是键值对存储模型的
Redis特点:
-
支持数据持久化
Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
-
支持多种数据结构
redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
-
支持数据备份
redis支持数据的备份,即master-slave模式的数据备份
Redis启动:
-
前台启动 redis-server
-
后台启动 redis-server &
-
启动redis服务时,指定配置文件:redis-server redis.conf &
Redis关闭:
-
通过kill命令:
ps -ef|grep redis #两个数字,前者是pid,后者是ppid 父进程 kill -9 pid #容易丢失数据
-
通过redis命令关闭
redis-cli shutdown
Redis客户端:
- redis-cli #默认连接ip为127.0.0.1,端口号为6379的redis
- redis-cli -h ip -p port #指定连接ip和端口号
- 关闭客户端,exit或quit
Redis基本知识
-
redis-benchmark 用来测试redis服务的性能
-
redis>ping 查看redis服务是否正常,如果正常,返回pong
-
info/info [信息段] 统计redis服务器的统计信息:
info #显示所有信息
info Replication #显示集群信息
-
redis的数据库实例:redis中的数据库实例只能由redis服务来创建和维护,开发人员不能修改和自行创建数据库实例;默认情况下,redis一启动会自动创建16个数据库实例,并且这些数据库实例没有名字,只有编号,从0-15.使用时,通过编号来使用数据库。
默认情况下,redis客户端连接的是0号数据库实例。可以使用select index切换数据库编号
-
dbsize 查看当前数据库中key的个数,也就是数据的个数
-
keys * 查看当前数据库实例中所有的key
-
flushdb 清空当前数据库
-
flushall 清空所有的数据库
-
config get * 查看redis中所有的配置信息
config get parameter 查看指定配置信息
Redis的5种数据结构
字符串 string 单key:单value username:zhangsan age:20
list列表 list 单key:多value contacts:133817929,email,address
set集合 set 单key:多value(无序) zhixiashi:bj,cq,sh
pojo对象 hash 单key:对象(属性:值) student:id:1001,name:zs,age:20
set排序集合 zset 单key:多value(有序,顺序由自己排序):city:2000 bj,2500 sh,1000 tj,1200 cq 前面的数字是自己指定的,它会自动排序
Redis常用指令
关于key的命令
-
keys pattern 查找所有符合通配符的key * 表示0或多个字符,?表示单个字符,[]表示选择[]中的一个字符,里面不用逗号分开
-
exists key [key key key ……] 判断key再数据库中是否存在, 如果存在返回1,否则返回0
-
move key index 移动指定key到指定的数据库实例
-
ttl key 查看指定的key剩余生存时间 ,如果key不存在返回-2,如果key没有设置ttl ,返回-1
expire key second 设定key存在的秒数
-
type key 查看key的数据类型
-
rename key newkey 重命名key
-
del key [key key ……] 删除指定的key 返回值是实际删除的数量
关于String类型数据的操作命令
- set key value 将string类型数据保存到redis中
- get key 从redis中获取string类型数据
- append key value 追加字符,如果key不存在,则新创建一个key,并且把value设置为value
- strlen key 获取字符串数据长度
- incr key 将字符串数值进行加1运算,返回加一之后的数据,如果key不存在,则默认该key值为0
- decr key 将字符串数值进行减一运算,返回减一之后的数据,如果key不存在,则默认该key值为0
- incrby key offset 将字符串数值进行加运算,返回加之后的数据,如果key不存在,则默认该key值为0,offset是要加的值
- decrby key offset
- getrange key startindex endindex 获取字符串中的子字符串,starindex 和endindex是闭区间,下标可以是负数
- setrange key startindex value 从startindex开始修改字符串中的子字符串
- setex key seconds value设置字符串的同时,设置最大生命周期
- setnx key value 当key已经存在时,设置失败
- mset k1 v1 k2 v2 k3 v3…… 批量设置数据
- mget k1 k2 k3 …… 批量获取数据
- msetnx k1 v1 k2 v2 k3 v3……批量设置数据,只有所有key都不存在才设置成功,否则只要有一个key存在,就全部放弃设置
关于list类型数据的操作命令
- lpush listkey value [value value ……] 将一个或多个值依次插入到列表的表头
- lrange listkey startindex endindex 获取列表中指定下标区间的元素
- rpush listkey value [value value ……] 将一个或多个值依次插入到列表的表位
- lpop listkey 从指定列表中移除并返回列表中的表头元素
- rpop listkey 从指定列表中移除并返回列表中的表尾元素
- lindex listkey index 获取列表中指定下标的元素
- llen listkey 获取指定列表的长度
- lrem listkey count value 移除指定列表中count个特定值的元素,count>0从左侧开始移除,count<0从右侧开始移除,count=0,移除所有等于value的元素
- linsert listkey before|after pivot value 在指定列表中的指定位置之前或者之后插入value
- lset listkey index value 修改指定index的value值
- ltrim listkey start stop 截断指定长度的列表成为新列表,原来的列表被覆盖
关于set类型数据的操作命令
- sadd key value [value v v v ……]将一个或多个元素添加到集合中,如果元素已存在,则会忽略该元素
- smembers key 获取指定集合中所有的元素
- sismember key value 判断指定元素在集合中是否存在,存在返回1 不存在返回0
- scard key 获取指定集合的长度
- srem key value [v v v……] 移除集合中一个或多个元素,不存在的元素会被忽略,返回成功移除的个数
- srandmember key count 随机获取集合中的一个元素,或count个,count>0随机获取的多个元素之间不能重复,count<0可以重复
- spop key [count] 从指定集合中随机移除一个或多个元素,返回该元素
- smove source dest value将指定集合中的指定元素移动到另一个集合中
- sdiff key key key 求差集,返回第一个key中有的,别的key都没有的元素
- sinter key key key 求交集,返回交集组成新集合
- sunion key key key 求并集
关于hash类型数据的操作命令
- hset key field value [field value……] 将对象存储到哈希表中,对象以键值对表示,如果field存在,则会覆盖
- hget key field 获取哈希表中指定field的值
- hmset key field value [field value……] 与第一个功能重复了,可以设置多个field value
- hmget key field field 批量获取field的值
- hgetall key 获取所有field和value
- hdel key field field 删除一个或多个field
- hlen key 获取field的个数
- hexists key field 判断是否存在某个field,存在返回1,不存在返回0
- hkeys key 获取所有field
- hvals key 获取所有的值
- hincrby key field int 对field的值进行整数加法运算
- hincrbyfloat key field float对field的值进行浮点数加法运算
- hsetnx key field valuefield value 如果field存在,则无法放置
关于zset类型数据的操作命令
- zadd key score value score value 将value及其socre加入key,其中score只用于排序,必须是数字,默认从小到大排序
- zrange key start end [withscores] 获取zset指定下标区间(从小到大)的元素,
- zrevrange key start end [withscores] 获取zset指定下标区间(从大到小)的元素
- zrangebyscore key min max [withsocres] 根据分数获取指定区间(从小到大)的元素
- zrevrangebyscore key min max [withsocres] 根据分数获取指定区间(从大到小)的元素
- zrem key value value 删除一个或多个元素
- zcard key 获取所有元素的个数
- zrank key value 获取指定元素的排名,返回下标
- zrevrank key value 获取指定元素的反向排名
- zcount key min max 获取分数在指定区间的元素的个数
- zscore key value 获取指定元素的分数
redis配置文件
-
要使用配置文件,在启动redis服务时,需要指定所使用的配置文件 redis-server redis.conf &
-
redis配置文件中关于网络的配置
port:指定redis服务所使用的端口,默认6379
bind:配置客户端连接redis服务时,所使用的ip地址。默认可以使用reids服务所在主机上任何一个ip都可以;
如果使用了配置了bind和port的配置文件,则客户端连接redis服务时,必须指定port和bind
redis-cli -h ip -p port
-
tcp-keepalive:tcp连接保活策略,单位为秒,假设为60秒,则server端每60秒会向连接空闲的客户端发起一次ack请求,以检查客户端是否已经挂掉,若挂掉,则会关闭该连接,如果设置为0,则不会进行保活检测。
-
loglevel:日志级别,开发时可以设为debug,生产阶段通常设置为notice或者warning
-
logfile:指定日志文件名,
-
databases:配置redis数据库的个数,默认16个
-
requirepass:需要另一个参数protected-mode为yes
redis持久化
RDB策略
-
RDB Redis Database:是redis默认的持久化方案,在指定的实践间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。redis重启会通过加载dump.rdb文件来恢复数据。
save :redis在seconds秒内key改变了changes次,就会进行持久化操作。
一般是1min1万次,5分钟10次,15分钟1次。
-
stop-writes-on-bgsave-error:当bgsave快照操作出错时停止写数据到磁盘,设置为yes可以保持数据一致性。
-
rdbcompression:存储到磁盘的数据是否压缩,设置为yes时,redis会采用LZF算法进行压缩。
-
rdbchecksum:存储快照后,redis可以使用CRC64算法来进行数据校验。
-
dbfilename:redis持久化数据生成的文件名,默认dump.rdb
-
dir:持久化数据生成文件保存的目录,默认时./,即redis启动目录
AOF策略
-
AOF append only File,采用操作日志来记录进行每一次写操作,每次redis服务启动时,都会重新执行一边操作日志中的指令。
-
appendonly:配置是否开启AOF,yes开启no关闭
-
appendfilename:AOF保存文件名
-
appendfsync:AOF异步持久化策略
always:同步持久化,每次发生变化立刻写入磁盘
everysec:默认,每秒存一次
no:不即时同步,由os决定合适同步
-
no-appendfsync-on-rewrite:重写时是否可以运用appendfsync,默认为no
-
auto-aof-rewrite-percentage:设置重写的基准百分比
-
auto-aof-rewrite-min-size:设置重写的基准值
redis事务
-
事务:把一组数据库操作放在一起执行,来保证操作的原子性,要么同时成功,要么同时失败。
-
redis事务:允许在把一组redis命令放在一起执行,保证命令执行的序列化,但不保证命令的原子性。
-
multi:标记事务的开始。
-
exec:执行事务队列
-
redis的事务只能保证部分原子性:
如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,能保证事务原子性。
如果一组命令中,有在压入事务队列过程中正常,但执行时发生错误的命令,则只会影响发生生错误的命令,不会影响其他命令的执行,不能保证事务原子性。
-
discard:清除所有已经已经压入队列中的命令,并且结束整个事务
-
watch:监控某一个键,当事务在执行过程中,此键代码的值发生变化,,则本次事务放弃执行,否则正常执行
-
unwatch:放弃监控所有键
redis消息发布与订阅
redis客户端订阅频道,消息的发布者往频道上发布消息,所有订阅此频道的客户端都能接收到消息。
- subscribe channel1 channel2:消息的订阅命令,订阅一个或多个频道的消息
- publish channel1 message:将消息发布到指定频道
- psubscribe:订阅一个或多个频道,频道名支持统配符
redis集群
redis的主从复制,主机数据更新后根据配置和策略,自动同步到从机的master/slave机制,master以写为主,也可以读,slave则只能读不能写。
搭建一主二从redis集群
-
搭建三台redis服务:一般而言需要三台机器,但也可以模拟一台机子上用不同的端口号(通过修改配置文件)启动redis。
修改配置文件:
bind:127.0.0.1 #为了方便,实际开发得用实际ip
port:6379 #每个端口配置文件都改成需要的端口
pidfile /var/run/redis_6379.pid #最好改一下,和端口同名
logfile “6379.log” #日志文件
dbfilename dump6379.rdb #暂存文件
-
查看三台redis服务在集群中的主从角色
info replication
Replication
role:master #角色都是主机,互不影响
connected_slaves:0
master_replid:f38b6bbba266b82835d4da04f7660abc2e27a426
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 -
设置主从关系,让6379为主机,6380和6381为从机,:设从不设主,主机不用动,修改从机即可,
命令:slaveof ip port
全量复制:一旦主从关系确定,会自动把主机上已有的数据同步到所有的从机
增量复制:在主机上添加数据,会自动同步到所有从机
读写分离:主机可读可写,从机不能写
-
主机宕机:模拟主机宕机,关闭主机。从机没有任何变化,还是只能读,不能写。主机恢复后,一切正常
-
从机宕机:主机少一个从机,其他从机不变。从机恢复,会变成主机,所以需要重新设置主从关系。
-
假如主机宕机,可以选一个从机成为主机:
先断开主从关系:slaveof no one,
再成为主机:让别的从机成为指定机器的主机
-
假如之前的主机又恢复了,可以选择让他当从机或主机
-
从机也可以有从机
redis哨兵模式
时刻盯着主机,主机如果宕机,哨兵会按着一套规则找一个从机上位。
-
部署哨兵:提供哨兵配置文件:redis安装目录下的sentinel.conf(自带的默认的),可以自定义配置文件写上一句话:
sentinel monitor dc-redis localhost 6379 1
表示:指定监控主机的ip,port 得到哨兵的投票数,当哨兵投票数大于或者等于此数时,切换主从关系
-
新开窗口,启动哨兵:redis-sentinel sentinel.conf
-
主机宕机,哨兵自动选择一个从机上位
-
主机恢复,哨兵会将他变成从机,从属于新的主机
Redis序列化
序列化:把对象转化为可传输的字节序列过程成为序列化
反序列化:把字节序列还原为对象的过曾称为反序列化。
为何要序列化:为了对象可以跨平台存储和进行网络传输。进行跨平台存储和网络传输的方式就是IO,IO支持的数据格式就是自节数组。所以需要把对象转为字节数组的时候制定规则(序列化),以便之后可以还原数据(反序列化)。
常见序列化语言:JDK(不支持跨平台),json,xml,hessian,kryo(不支持跨语言),Thrift,protostuff
Jedis
将redis的命令封装以便再java中使用redis.
配置时需要让服务器端的bind绑定到真实的ip,而不是127.0.0.1