常用帮助地址
www.redisdoc.com
http://www.redis.cn/
Redis = remote dictionary server
redis是单线程模式的 一次只能处理一个请求,且区分大小写。
但redis的速度挺快的,主要原因是
1.redis是单线程模式的
2.redis的数据放在内存中
3.linux的机制多路复用IO
包含了以下几种数据格式:String、Map、list、set、有序集合 sorted sets
登录: ./redis-cli -h ip -p port
redis的命令
ping 正常时返回pong 查看当前redis是否正常
dbsize 查看当前库的key数量
select db 切换数据库,切换到第一个库
flushdb 删除当前库的所有数据
操作key、String、Hash、List、Set、Zset
操作key的命令
keys * 显示当前库所有key(生产不要用),可以使用通配符 ?一个字符 *-多个字符
exists key1 key2 是否存在当前key 返回数量
expire key seconds 设置已存在的key的生存时间,单位S。设置成功返回1,失败返回0
pexpire key milliseconds 设置已存在的key的生存时间,单位毫秒
expireat key timestamp 设置key在某一个时间戳时过期
persist key 设置某个key永远不会过期
ttl 返回key剩余的生存时间 -1永久 -2不存在
type 查看key对应的值是什么类型的
del key1 key2 从当前库中删除一个或者多个key,返回删除的数量
rename key newkey 键重命名。如果新键已经存在,则会被覆盖
renamenx key newkey 建重命名。新建不存在才可以重命名
key在redis实例之内迁移
key在两个不同redis的迁移
单key迁移
dump key --在源redis上将这个键值序列化转为RDB存储。
restore key ttl value --在目标redis上。restore将上面序列化的值进行复原。ttl代表过期时间,ttl=0代表不会过期
下面用一个 例子演示完整过程。 1)在源Redis上执行dump: redis-source> set hello world OK redis-source> dump hello "x00x05worldx06x00x8f<Tx04%xfcNQ" 2)在目标Redis上执行restore: redis-target> get hello (nil) redis-target> restore hello 0 "x00x05worldx06x00x8f<Tx04%xfcNQ" OK redis-target> get hello "world"
多个key迁移
migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key]]
下面对migrate的参数进行逐个说明: ·host:目标Redis的IP地址。 ·port:目标Redis的端口。 ·key|"":在Redis3.0.6版本之前,migrate只支持迁移一个键,所以此处是要迁移的键,但Redis3.0.6版本之后支持迁移多个键,如果当前需要迁移多个键,此处为空字符串""。 ·destination-db:目标Redis的数据库索引,例如要迁移到0号数据库,这 里就写0。 ·timeout:迁移的超时时间(单位为毫秒)。 ·[copy]:如果添加此选项,迁移后并不删除源键。 ·[replace]:如果添加此选项,migrate不管目标Redis是否存在该键都会 正常迁移进行数据覆盖。 ·[keys key[key...]]:迁移多个键,例如要迁移key1、key2、key3,此处填 写“keys key1 key2 key3”。
redis可以操作多种类型的数据,下面对类型数据操作进行描述
使用redis存储数据的时候,有时候为了查看的方便,通常会有层级或者说是目录,这时候我们在set的时候,需要将key值使用“:”的符号来区分层级关系
比如:set(“a:b”, “123”),那么在redis中就是a目录下的key值为b的value为123。
操作String型数据
set key value 设置值,已存在的覆盖掉
set的几个选项
ex seconds : 为键设置秒级过期时间
px milliseseconds : 为键设置毫秒级过期时间
nx 键必须不存在,才可以设置成功。用于添加
xx 与nx相反,键必须存在,才可以设置成功。用于更新
get key 获取指定key的值,nil没有值
incr key 把key的值+1。对整数值进行计算,否则报错;若key不存在,初始化为0 再加1
decr key 把key的值-1。对整数值进行计算,否则报错;若key不存在,初始化为0 再减1
append key value 把value追加到key后。返回追加后的长度;若key不存在,等同于set命令
strlen key 求长度,没有key返回0
getrange key start end 求子段,类似subString.最左边是0,最右边是-1
setrange key offset value 用value覆盖offset开始的内容
mset 一次性设置多对K-V
mget 一次性获取多对K对应的值
操作Hash型数据-用来存java对象
hset key field value 将key中的field字段的值设为value。如果key不存在,则新建hash表,执行赋值。如果field存在,则覆盖值
返回值:如果field是hash中新field。且设置成功,返回1
如果field已经存在,旧值覆盖新值,返回0
hget key field 获取哈希表key中field的值
hmset key field value [field value] 一次性设置多个值
hmget key field [field] 一次性获取多个值
hgetall key 获取key中所有的字段和值
hdel key field [field] 删除多个field字段。返回删除field的数量
hkeys key 获取key中所有的field
hvals key 获取key中所有的值
hexists key field 查看哈希表key中。field是否存在、存在1,不存在0
操作List型数据
lpush key value[value] 将一个或者多个值添加到列表key的表头(最左边)
rpush key value[value] 将一个或者多个值添加到列表key的表尾(最右边)
lrange key start stop 获取key中指定区间内的元素
lindex key index 获取下标的值
llen key 求key成员的个数
lrem key count value 删掉重复的几个数据。count=0 代表全删
lset key index value 将key下标为index的元素值设置为value
linsert key BEFORE|AFTER pivot value 将value插入到key中位于值pivot之前或者之后的位置
lpop 从列表最左侧取出数据,并删掉
rpop 从列表最右侧取出数据,并删掉
操作set集合数据-无序、不可重复
sadd key member [member] 将一个或者多个member加入到集合key中。已经存在的member将会被忽略,不会再加入
smembers key 获取key里面所有的成员
sismember key member 判断member元素是否是集客key的成员 1-存在 0-不存在
scard key 获取集合里面的元素个数
srem key member [member] 删除集合key中的一个或者多个member元素
srandmember key [count] 随机返回集合中count个元素,但是并没有删除,元素依然在集合中。count为负数,取出的值可能是重复的
spop key [count] 随机从集合中删除count个元素
sinter key1 key2 取两个集客的交集
sunion key1 key2 取两个集客的并集
操作zset有序集合数据-有序、不重复的。
通过分数来为集合中的成员进行排序。同分数通过字典顺序排序
zadd key score member [score member] 将一个或者多个member元素和score元素 加入到有序集合key中。如果member已经存在,则更新值。score可以是整数或者浮点数
zrange key start stop [withscores] 查询有序集合指定区间内的元素。withscores会将参数一并返回
zrevrange key start stop [withscores] 用法同zrange。只是显示顺序反过来,按照score从大到小
zrem key member [member] 删除集合中key中 一个或者多个成员
zcard key 获取有序集合key中的元素成员个数
zrangebyscore key min max [withscores] [LIMIT offset count] 获取有序集合中,所有score值介于min和max之间(包括min和max)的成员。LIMIT是分页。offset
如果使用 (min (max 则代表--不包括min和max的成员
-inf集合中的最小值
+inf集合中的最大值
zrevrangebyscore key max min [withscores] [LIMIT offset count] 用法类似zrangebyscore。注意max和min的位置,显示顺序反过来,按照score从大到小
zcount key min max 统计key中score值在min和max之间的成员数量
事务
保证几个redis命令执行时中间不会被其他任何操作打断。
multi 标志事务开始
exec 标志事务的提交。如果执行exec之前 某个命令是错的,那么整个事务都会被取消。如果执行exec之后 某个命令失败,其他命令会继续执行
discard 标志取消事务
watch key [key] 监视一个或者多个key,如果在事务执行前这个key被其他命令所改动,那么事务将被打断
unwatch 取消所有的watch命令
持久化:优先使用aof。
RDB机制。将内存的数据写入到磁盘的二进制文件中,重启时从rdb文件读取。N秒内数据集至少有M个key改动。通过配置redis.conf文件实现。不能100%保存数据
redis.conf需要的配置项
a.save <seconds> <changes>
b.dbfilename 设置RDB文件名称,默认是dump.rdb
c.dir指定RDB文件的存储位置,默认是./当前目录
AOF方式。redis每次接收到一条可以改变数据的命令时,就把该命令写入一个AOF文件中。当redis重启时,通过AOF文件恢复.通过配置redis.conf文件实现
redis.conf需要的配置项
a.appendonly 默认是no,改成yes开启aof持久化
b.appendfilename 指定aof文件名,默认文件名是appendonly.aof
c.dir 指定RDB和AOF文件存放的目录,默认是./
d.appendfsync 配置向aof文件写命令数据的策略
- no 不主动进行同步操作,而是交给操作系统来做(30S一次),比较快但是不是很安全
- always 每次执行写入都会执行同步,慢一些但是比较安全
- everysec 每秒执行一次同步操作,比较平衡。默认项
e.auto-aof-rewrite-min-size 允许重写最小aof文件大小。默认是64M.当aof文件大于64M时。开始整理aof,去掉无用的操作命令,缩小aof文件
主从复制 master/slave。一般在从上进行持久化
主redis用来写。从redis用来读,从不能写
主从复制例子6380为主 6382和6384为从
1.编辑主6380.conf。在空文件加入如下内容
include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
daemonize yes --后台启动应用。相当于./redis-server &
port 6380
pidfile /var/run/redis_6380.pid --自定义文件,表示当前程序的pid,进程id
logfile 6380.log
dbfilename dump6380.rdb --持久化文件名称
2.编辑从6382.conf。在空文件加入如下内容
include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
daemonize yes --后台启动应用。相当于./redis-server &
port 6382
pidfile /var/run/redis_6382.pid --自定义文件,表示当前程序的pid,进程id
logfile 6382.log
dbfilename dump6382.rdb --持久化文件名称
slaveof 127.0.0.1 6380
3.编辑从6384.conf。在空文件加入如下内容
include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
daemonize yes --后台启动应用。相当于./redis-server &
port 6384
pidfile /var/run/redis_6384.pid --自定义文件,表示当前程序的pid,进程id
logfile 6384.log
dbfilename dump6384.rdb --持久化文件名称
slaveof 127.0.0.1 6380
启动3个redis主从节点。分别登录3个redis后 用info replication查看信息
容灾
手动容灾处理
1.在要升级为主的机器上执行 slaveof no one 将一台slave服务器提升为master
2.在其他备份从节点上执行 slaveof 127.0.0.1 6382 将slave挂到新的master上
哨兵:自动容灾
监控:Sentiel不断监控主服务和从服务是否按照预期正常工作
提醒:被监控的redis出现问题时,sentinel会通知管理员或者其他应用程序
自动故障转移:监控的主redis不能正常工作,sentinel会开始进行故障迁移操作。将某一个从升级为主。让其他从挂到新的主服务器。同时向客户端提供新的主服务器地址
sentinel monitor 全部监控master节点
集群的容灾
redis3.0后支持集群部署。集群一般需要6个节点,使用ruby进行整个集群的关联。为3主3从,主从之间和进行复制。
如果集群的某个分槽的主从都挂了,分槽不可用,认定这个集群不可用
如果集群超过一半的主节点都挂了,也认定这个集群不可用
设置密码
设置密码 修改redis.conf 中的requirepass
Jedis+commons-Pool
每秒输出一次redis的内存使用量
redis-cli -r 100 -i 1 info | grep used_memory_human
redis发布订阅模式
发布消息
publish channel message
订阅消息
subscribe channel [channel]
一些优化方案
缓存更新优化----合理安排缓存清除时间。
缓存粒度控制----合理存储字段,不将整个表的字段都存下来,只存热点字段,节省内存和反编译时间
穿透优化----恶意攻击或者爬虫时,大量数据redis中没有,直接到存储层进行查询,存储层也没有,导致redis缓存大量的空对象。
解决办法:
1.将空对象设置较短的过期时间(不超过5分钟)
2.布隆拦截器。将常用数据都缓存到redis中。拦截器发现redis中没有,也认定存储层没有。不去访问存储层。
无底洞优化----横向增加redis节点的时候,获取数据需要消耗大量的网络时间,达不到优化目的
雪崩优化----redis服务不可用 或者大量key同时到期,大量的数据请求直达存储层。造成存储层优化
解决办法:
1.保证缓存层服务高可用
2.不同的key,设置不同的过期时间,具体值可以根据业务决定,让缓存失效的时间点尽量均匀
3.使用Hystrix组件为后端限流并降级
热点key重建优化----一个热点key失效后,大量的访问使得多个线程同时开始对该热点key进行缓存,造成死锁
解决办法:
1.设置数据永不过期
2.互斥锁。只允许一个现场进行缓存重建。其他线程等待重建完成后,重新获取数据。
String get(String key) { // 从Redis中获取数据 String value = redis.get(key); // 如果value为空,则开始重构缓存 if (value == null) { // 只允许一个线程重构缓存,使用nx,并设置过期时间ex String mutexKey = "mutext:key:" + key; if (redis.set(mutexKey, "1", "ex 180", "nx")) { // 从数据源获取数据 value = db.get(key); // 回写Redis,并设置过期时间 redis.setex(key, timeout, value); // 删除key_mutex redis.delete(mutexKey); } // 其他线程休息50毫秒后重试 else { Thread.sleep(50); get(key); } } return value; }