Redis
一、安装
docker 安装 redis
- 查找redis镜像 docker search redis
- 拉去镜像 docker pull redis
- 运行镜像
docker run -p 6379:6379 -v $(pwd)/redis/data:data -d -name r01 redis redis-server --appendonly yes
1. -p 6379:6379 进行端口映射
2. -v $(pwd)/redis/data:data 将容器中的data挂载到当前目录下redis下的data
3.redis-server --appendonly yes : 在容器执行redis-server启动命令,并打开redis持久化配置
docker run -p 6378:6379 --name r04 -v $(pwd)/data:/data -v
$(pwd)/etc/redis.conf:/etc/redis.conf -d redis redis-server /etc/redis.conf --
appendonly yes
1. 挂载conf必须指定到redis.conf
2. redis.conf中daemonize属性必须为no 因为docker运行时-d本身就是指守护进程
- 查看容器分配的ip docker inspect r01 | grep IPAddress
- 连接reids
docker exec -ti r01 redis-cli
#直接进入redis 指定 host 和 p
docker exec -ti r01 redis-cli -h localhost -p 6379
docker exec -ti r01 redis-cli -h 127.0.0.1 -p 6379
docker exec -ti r01 redis-cli -h 172.17.0.3 -p 6379
#使用默认host(127.0.0.1)和p(6379)
docker exec -it r01 redis-cli
#先进入容器再进入redis
docker exec -it r01 bash
#使用默认host和p
redis-cli
#注意,这个是容器运行的ip,可通过 docker inspect redis_s | grep IPAddress 查看
linux安装redis
#获取redis压缩包
#具体下载版本到这个网页查找
#http://download.redis.io/releases/
wget http://download.redis.io/releases/redis-5.0.6.tar.gz
#解压缩
tar -zxvf redis-5.0.6.tar.gz
#改名
mv redis-5.0.6.tar.gz redis
#进入redis并用gcc make进行编译
cd redis
make
cd src
make install PREFIX=/usr/local/redis
#移动配置文件到安装目录下
mkdir /usr/local/redis/etc -p
cd ..
mv redis.conf /usr/local/redis/etc/
#配置redis为后台启动
vim redis.conf //将daemonize no 改成daemonize yes
#将redis加入到开机启动
#给redis配置环境变量
echo 'export PATH=$PATH:/usr/local/redis/bin/' >> /etc/profile
source /etc/profile
#启动redis
redis-server
#进入redis
redis-cli
Hello World
- 启动redis docker exec -it r01 redis-cli -h localhost -p 6379
- set k1 hello
- get k1
二、启动及之后杂项
默认数据库
-
默认数据库数量 :11
-
切换默认数据库 select +num[0~15]
DBSIZE
显示数据的数量
keys *
查看所有键
FLUSHDB
清除当前库下的所有kv
FLUSHALL
清除所有库下的kv
三、数据类型
五大数据类型
1、String 字符串
介绍
- String 是 redis中最基本的数据类型
- String 类型是二进制安全的,意思是redis的String可以包含任何数据类型,比如jpg图片或者序列化对象
- String 类型是最近本的数据类型,一个redis字符串value最多可以是512M
操作
-
append key v
将v追加到key的值中
-
strlen key
测量key的长度
-
incr key
使key对应的value加1 (value 必须为整型)
-
decr key
使key对应的value减1 (value必须为整型)
-
getrange key x y
获取字key值的第x位到第y位
-
setrange key x v
将字符串v的在key的x位插入
-
setex key s value
设置kv时 指定kv的生存时间 到期自动死亡
-
setnx key value
当key不存在时 设置 value
当key存在时 不进行覆盖
-
mget/mset/msetnx
同时进行多个赋值,多个查找
2、Hash 哈希,类似java里的Map
操作
-
hset/hget/hmset/hmget/hgetall/hdel
#设置哈希user 的name为zyh age为20 hset user name zyh hset user age 20 #获取哈希user name的值和age的值 hget user name zyh hget user age 20 #哈希user一次设置多个kv(qq和gender) hmset user qq 534956355 gender 1 #一次获取哈希user的多个值 hmget user name age qq gender zyh 20 534956355 1 #获取哈希user的所有key和value hgetall user name zyh age 20 qq 534956355 gender 1 # hdel user qq hgetall user name zyh age 20 gender 1
-
hlen key
#获取哈希user中kv的个数 hlen user
-
hexists key child_key
#判断哈希user中是否存在键name和qq hexists user name 1 hexists user qq 0
-
hkeys/hvals key
#获取哈希user中所有的键 hkeys user name age gender #获取哈希user中所有的值 hvals user zyh 20 1
-
hincrby/hincrbyfloat key num
hset user score 80 #将哈希user的score增加5 hincrby user score 5 85 #将哈希user的score增加1.5 ----会将整形转为浮点型 hincrbyfloat user score 1.5 86.5 #将哈希user的score增加1 ----- hincrby只能对整形操作 hincrby user score 1 (error) ERR hash value is not an integer #将哈希user的score增加-1 hincrbyfloat user score -1 85.5
-
hsetnx key child_key child_val
#如果哈希user中不存在name则添加 hsetnx user name kbw 0 #如果哈希user中不存在qq则添加 hsetnx user qq 534956355 1
3、List 列表
模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l1j3CZzO-1574146410069)(imgs/list.png)]
操作
-
lpush/rpush/lrange
#将1 2 3 4从上往下压栈 lpush l1 1 2 3 4 #将1 2 3 4从下往上压栈 rpush l2 1 2 3 4 #将l1 l2 搜索出来() lrange l1 0 -1 4 3 2 1 lragne l2 0 -1 1 2 3 4 #将0从下往上压入l1 rpush l1 0 lrange l1 0 -1 4 3 2 1 0 #将0从上往下压入l2 lpush l2 0 lrange l2 0 -1 0 1 2 3 4
-
lpop/rpop (从上/从下取出一个值)
#从上边取出一个值 lpop l1 4 lrange l1 0 -1 3 2 1 0 #从下边取出一个值 rpop l1 0 lrange l1 0 -1 3 2 1
-
lindex index 显示从上往下显示索引在index位的值
#从上往下显示索引的值 lindex l1 1 2
-
llen 显示列表的长度
#显示列表的长度 llen l1 3
-
lrem key count v 将key中value为v的值删除count个
#将3 3 4 4从上往下压入l1 lpush l1 3 3 4 4 lrange l1 0 -1 4 4 3 3 3 2 1 #从上往下将值位3 的移除两个 lrem l1 2 3 lrange l1 0 -1 4 4 3 2 1 #将3 4从上往下压入l1 lpush l1 3 4 #从上往下将值位4 的移除两个 lrem l1 2 4 lrange l1 0 -1 3 4 3 2 1
-
ltrim key start end 从上往下将列表索引在start到end之间的值截取并赋给当前列表
#将l1中索引从1到3的值截取并赋给l1 ltrim l1 1 3 lrange l1 0 -1 4 3 2
-
**rpoplpush l1 l2 ** 从l1下去一个值,将该值从上往下压入l2
lrange l1 0 -1 4 3 2 lrange l2 0 -1 0 1 2 3 4 #从l1下去一个值,将该值从上往下压入l2 rpoplpush l1 l2 lrange l1 0 -1 4 3 lrange l2 0 -1 2 0 1 2 3 4
4、Set 集合
操作
-
sadd/smembers/sismember
#给set s1赋值(set去重复) sadd s1 1 1 2 2 3 3 #将s1的中的值打印出来 smembers s1 1 2 3 #判断1是否是s1的成员 是返回1 否返回0 sismember s1 1 1
-
scard key
#打印s1中值的数量 scard s1 3
-
srem key value
#移除s1中值为2和3的项 srem sl 2 3 smembers s1 1
-
srandmember key count
sadd s1 1 2 3 4 5 6 7 8 #随机在s1中随机打印count个值 strandmember s1 count
-
spop key count
#在s1中随机取出count个值 spop s1
-
smove key1 key2 v
sadd s1 1 2 3 sadd s2 4 5 6 #将s1中的2取出来给s2 smove s1 s2 2 smembers s1 1 3 smembers s2 2 4 5 6
-
数学集合类
-
差集:sdiff key1 key2 相比于key1,key2中没有的值
sadd s1 1 2 3 4 5 sadd s2 1 2 3 x y #s1有s2没有的值 sdiff s1 s2 4 5 #s2有s1没有的值 sdiff s2 s1 x y
-
交集:sinter key1 key2
#s1和s2共有的值 sinter key1 key2 1 2 3
-
并集:sunion key1 key2
#s1和s2中所有的值(排序未知) sunion s1 s2 x 2 y 5 3 4 1
-
5、Zset sorted set:有序集合
介绍
再set基础上加了个score
set
sadd key v1 v2 v3
zset
zadd key score1 v1 score2 v2 score3 v3
操作
-
zadd/zrange
#向z1中添加60~100 ,v1~v2 zadd z1 60 v1 70 v2 80 v3 90 v4 100 v5 #打印z1中的值 zrange z1 0 -1 v1 v2 v3 v4 v5 #打印z1中的值和score(默认 低到高) zrange z1 0 -1 withscores v1 60 v2 70 v3 80 v4 90 v5 100
-
zrangebyscore key startscore endscore [withscores] [limit offset count]
#打印z1中60(包含)到90(包含)的值 zrangebyscore z1 60 90 v1 v2 v3 v4 #打印z1中60(不包含)到90中的值 zrangebyscore z1 (60 90 v2 v3 v4 #打印z1中60(包含)到90(包含)的值中第二个到第三个 zrangebyscore 60 90 limit 1 2 v2 v3
-
zrem key value
#移除z1中值为100的项 zrem z1 v5 1
-
zcard/zcount key socre区间
#查看z1中有多少个值 zcard z1 4 #查看60(不包含)到80(包含)中有多少个值 zcount z1 (60 80 2
-
zscore key value
#查看z1中值为v2所对应的score zscore z1 v2 70
-
zrank key value/zrevrank key values
#查看z1中v2在z1中的排名 zrank z1 v2 1 #查看z1中v2在z1中的排名(高到低) zrevrank z1 v2 2
-
zrevrange
#打印z1中的值(高到低) zrevrange z1 0 -1 v4 v3 v2 v1
-
zrevrangebyscore key startscore endscore
#打印出z1中80(包含)到60(不包含)的值(高到低) zrevrangebyscore z1 80 (60 v3 v2
_Reids_Key关键子
1、EXISTS key
判断键是否存在
返回 1存在
返回 0不存在
2、move key db
将某个kv移动到db库中
例:
move k1 2
#将key为k1的键值对移动到第二个库中
3、expire key 秒钟
为给定的key设置过期时间
4、ttl key
查看还有多少秒过期
-1 表示永不过期
-2 表示已过期或不存在
5、type key
查看你的key是什么类型
6、del key
删除键值对
四、解析配置文件
五、持久化
RDB (Redis DataBase)
RDB是整个内存的压缩过的Snapshot,RDB的数据结构,可以配置符合的快照触发条件
注意:
shutdown时会触发,即在服务关闭的时候会触发RDB将此时内存的数据保存到默认的dump.rdb文件中
flushall命令也会,也会产生dump.rdb文件,但里面时空的,无意义
#SnapShot
#save <second> <count>
#设置多少秒(second)设置多少次(count)时触发
#默认
#一分钟改了1万次
#或者五分钟改了10次
#或者十五分钟改了1次
#直接使用save/bgsave 进行保存
#save 只管保存,其他不管,全部阻塞
#bgsave 异步进行快照,仍然响应客户端请求。
AOF (Append Only File)
默认关闭
保存位置
aof的启动修复/恢复
redis-check-aof
rewirte
重写:将语句进行压缩 ,列如
set k1 2
incr k1
incr k1
可以写为 set k1 4
重写机制
redis会记录上次重写时的AOF的大小,默认配置时当AOF文件的大小时上次rewrite后大小的一倍且文件大于mb时触发
六、事务
是什么
可以一次执行多个命令,本质是一组命令的集合。
一个事务中的所有命令都会序列化,
按顺序地串行化执行执行而不会被其他命令插入,不许加塞
能干嘛
一个队列中,一次性,顺序性,排列性的执行一系列命令
怎么玩
常用命令
- DISCARD 取消事务,放弃执行事务内的所有命令
- EXEC 执行所有事务块的命令
- MULTI 标记一个事务块的开始
- UNWATCH 取消WATCH 命令对所有key的监视
- WATCH key [key … ] 如果在事务执行前这个(或这些)key被其他命令所改动,呢么事务将被打断
正常执行
放弃执行
全体连坐
命令错误时
要么全部成功 要么全部失败
冤头债主
执行错误时
错的失败,成功的成功
watch监视
相当于乐观锁
一旦执行exec之前的所有监控都会被取消
3阶段
- 开启:以MULTI开始一个事务
- 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
- 执行:有EXEC命令触发事务
3特性
- 单独的隔离操作:食物中的所有命令都会序列化、按顺序地执行。事务在实行的过程中,不会被其他客户端发送来的命令请求打断
- 没有隔离级别:队列中的命令没有提交之前都不会实际的执行,因为事务提交前任何指令都不会被实际执行,也就是说不存在“事务内的查询要看到是物理的更新,在事务外查询不能看到”这个让人万分头疼的问题
- 不保证原子性:redis同一个事务中如果有一跳命令执行失败,其后的命令仍然会被执行,没有回滚
七、主从复制
一主二仆
一个主库连个从库
主库挂了
从库依然是从库,连接状态变为失联。
主库回来后依然是主库,从库连接状体变为连接
从库挂了
该从库与主库解除关系,再次启动从库 变为主库 与 之前的主库不在有关系
结论:
- 从库不挂,则连接状态存在,否则连接状态一直保存
- 只要连接状态存在,就可以一直连接
薪火相传
主库<-从库<-从库
反客为主
当主库挂了之后,在从库执行SLAVEOF no one 则该从库变为新的主库。
其他从库 要么等原来的主库回来 要么 使用SLAVEOF选择新的主
哨兵模式
反客为主自动版
创建配置文件
sentinel.conf
配置要监视的库
sentinel monitor 名字(自己起) host p
当监视的主库挂掉后,在从库中选出新的从库
当原来的主库恢复后,变为新主库的从库