1、linux中指定配置文件启动
redis-server bconfig/redis.conf
2、客户端连接
redis-cli -h localhost -p 6379
3、关闭redis
ps -ef|grep redis
4、压力测试 自带的压力测试工具
redis-benchmark -h localhost -p 6379 -c 100 -n 100000 -c并发数 -n请求数
5、基础知识
redis中默认有16个数据库,默认使用第0个数据库
使用select进行切换数据库
keys * 查看所有的key
flushdb 清空当前库
flushall 清空所有数据库
redis是单线程的
6、基础命令
expire key 10 设置key 10秒后过期
ttl key 查看key的剩余过期时间 持久化的返回-1,已经过期的(不存在)返回-2 ,期间的返回剩余时间
exists key 判断key是否存在,返回1存在,返回0不存在
del key 删除指定key
move key database 将key移动到指定数据库
type key 查看key是什么类型
五大数据类型
String 字符串
append key value 给value后追加value append name hello 返回是追加后字符串的长度 -- bwhmhello
strlen key 返回字符串长度
incr key 值+1 value如果不是数字的话 (error) ERR value is not an integer or out of range
decr key 值-1 value如果不是数字的话 (error) ERR value is not an integer or out of range
incrby key num 值+num 指定步长增加
decrby key num 值-num 指定步长减少
getrange key start end 获取[start,end]范围的字符串 getrange key 0 -1 获取全部字符串
setrange key offset value 从指定位置开始修改数据 替换
setex (set with expire) setex key second value 设置值的时候带上过期时间
setnx (set if not exist) setnx key value 在key不存在的时候再设置,直接set会覆盖
mset key1 value1 key2 value2... 批量设置
mget key1 key2... 批量获取
msetnx key1 value1 key2 value2... 不存在的时候批量设置,操作符合原子性,若有一个存在,整体set失败
mset user:1:name zhangsan user:1:age 2 存储对象,比user:1 {name:zhangsan,age:2} 这样设计好一些
mget user:1:name user:1:age
getset key value
List 列表
指令都加L
lpush key value 向list中放入值 左边
rpush key value 向list的尾部放入值 右边
lrange key start stop 获取list类型指定位置的数据 lrange list 0 -1 获取全部,lrange list 0 1 发现获取的是后添加的数据,可以想成 [...,第二次数据,第一次数据]
lpop key 移除list中的值 最左边
rpop key 移除list中的值 最右边
lindix key index 获取key中指定下标的值,下标从0开始
llen key 获取list的长度
lrem key count value 移除list中指定的值,list中可以放入重复的值,lrem list 2 one ,其中count 的值如果过大,会全部移除符合条件的值
ltrim key start stop 截取指定的长度,ltrim list 1 2 -》 three two
rpoplpush 移除列表中最后一个元素,并将这个元素移动到新的列表中 rpoplpush list otherlist
lset key index value 替换列表中指定下标的值,不存在列表或者不存在下标会报错
linsert key before|after pivot value 给列表中指定值的前面或者后面插入value linsert list before five hahaha
List实际上是一个链表,before node After ,left ,right都可以插入值
在两边插入或者改动值,效率最高,中间元素,相对来说效率会低一点点
消息队列(lpush rpop) 栈(lpush lpop)
set 集合
set中的值是不能重复的,命令开头都是s
sadd key member 给set中添加数据 可以同时添加多个,空格分隔 同时插入多个的时候,如果有重复的,不会插入该值,其余正常插入,返回结果是正常插入的数量
smembers key 查询指定key的所有元素
sismemeber key value 判断指定值是否在set中存在,有返回1,没有返回0
scard key 获取set中元素的个数
srem key member 移除指定set下的指定元素,成功返回1
srandmember key 在指定set中随机抽取一个元素
srandmember key count 在指定set中随机抽取count个元素
spop key 随机删除set集合中的一个元素
smove source destination member 从某个set集合中移除指定元素到另一个set集合
sdiff key1 key2 差集
sinter key1 key2 交集 共同好友
sunion key1 key2 并集
Hash 哈希
Map集合,key-map 值其实就是一个map集合,本质和string类型没有太大区别,还是一个简单的key-value
hset key field value set一个具体的key-value
hmset key field1 value1 field2 value2 set多个key-value
hget key field 获取一个字段值
hmget key field1 field2 获取多个字段值
hgetall key 获取全部的数据
hdel key field 删除某个字段
hlen key 获取hash的长度
hexists key field 判断key中某个字段是否存在
hkeys key 获取hash的所有key
hvals key 获取hash的所有value
hincrby key field num hash中指定key的字段增加num
hdecrby key field num hash中指定key的字段减少num
hsetnx key field value hash中指定key不存在的话set
hash更适合对象的存储,string更适合字符串的存储
ZSet 有序集合
在set的基础上,增加了一个值
zadd key score value 添加一个值
zadd key score1 value1 score2 value2 添加多个值
zrange key start stop 获取key中的范围数据 zrange key 0 -1 获取全部 从小到大
zrevrange key start stop 获取key中的范围数据 zrange key 0 -1 获取全部 从大到小
zrangebyscore key min max 获取key从负无穷到正无穷的数据,按照升序排列 zrangebyscores myzset -inf +inf
zrangebyscore key min max withscores 获取key从负无穷到正无穷的数据,按照升序排列,并显示score值
zrem key value 移除指定value
zcard key 获取有序集合中的个数
zcount key start stop 获取指定区间的值的个数
成绩表、工资表
带权重查询,普通消息,重要消息,紧急消息
排行榜应用
三种特殊数据类型
geospatial 地理位置
朋友定位、附近的人、计算打车距离
geoadd 添加地理位置
两级无法直接添加
有效的经度从-180度到180度
有效的纬度从-85.05112878度到85.05112878度
当插入的数据超过有效范围会返回错误信息
geoadd key 纬度 经度 名称
geopos key 名称 获取指定城市的纬度和经度
geodist key member1 member2 查询key中两个成员的直线距离,单位默认为m,后面可以指定单位,m,km,mi(英里),ft(英尺)
用于查询两人之间的距离
georadius 查询附近的人
georadius china:city 110 30 1000 km withdist withcoord count 2 查询经度为110,纬度为30附近1000km的成员,显示直线距离,显示经纬度,查询成员的数量
georadiusbymember 找出位于指定元素周围的元素
geohash 返回一个或多个位置的元素的geohash表示
geo底层的实现原理是zset,所以可以使用zset命令来操作geo
Hyperloglog
pfadd key value...
pfcount key
pfmerge key source...
如果允许容错,使用Hyperloglog就可以
如果不允许容错,使用 set 或者自己的数据类型就可以
Bitmap
事务
redis的单条命令是保证原子性的,但是事务不保证原子性
redis事务没有隔离级别的概念的,所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会被执行
redis事务的本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务的执行过程中,会按照顺序执行
一次性、顺序性、排他性
redis的事务:
1、开启事务 multi
2、命令入队 .............
3、执行事务 exec 或者 放弃事务 discard
正常执行事务
放弃事务 事务在执行完之后就会消失,再次使用时需要重新开启事务
编译型异常(代码有问题,命令错误),事务中所有的命令都不会执行
运行时异常(1/0) 如果事务队列中存在语法错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
监视
redis监视测试
测试多线程修改值,使用watch可以当做redis的乐观锁操作
第一个客户端开启事务,不执行,第二个客户端直接修改money的值,修改完成之后,第一个客户端执行事务,会返回nil
如果执行失败,获取最新的值即可
Jedis
jedis是redis官方推荐的java连接开发工具
springboot整合redis
redisTemplate.opsForValue string类型
redisTemplate.opsForList
redisTemplate.opsForSet
redisTemplate.opsForHash
redisTemplate.opsForZset
redisTemplate.opsForGeo
redisTemplate.opsForHyperLogLog
编写自己的redistemplate,解决编码的问题
Redis.conf详解
网络
bind 127.0.0.1 #绑定的ip
protected-mode yes #保护模式
port #端口设置
通用
daemonize yes # 以守护进程的方式运行,默认是no,我们需要自己开启为yes
pidfile /var/run/redis.6379.pid # 如果以后台方式运行,我们需要指定一个pid文件
日志
loglevel notice # 生产环境 debug 测试环境 verbose 类似于debug模式 warining 仅输出重大错误,一般为notice不需要改
logfile "" # 日志的文件位置名
database 16 # 默认16个数据库
always-show-logo yes #是否总是显示logo
快照
Redis持久化
redis是内存数据库,如果不将内存中的数据保存到磁盘上,那么一旦服务进程退出,服务器中的数据库状态也会消失,所以redis提供了持久化功能
RDB Redis DataBase
触发机制:
1、save的规则满足的情况下,会自动触发rdb规则
2、执行flushall命令,会触发rdb规则
3、退出redis,也会产生rdb文件
如何恢复rdb文件中的数据?
AOF Append Only File
将所以的命令都记录下来,恢复的时候就是把这个文件全部执行一遍
appendonly no 默认不开启,yes开启 重启生效
默认按秒进行记录,如果宕机,最后一秒的数据会丢失
appendonly.aof 是日志级别的记录写操作的文件,使用vim指令打开可以看到指令,可以人为的进行破坏,破坏之后,再次启动redis是报错,连接不上,可以使用redis提供的redis-check-aof工具进行修复
redis-check-aof --fix appendonly.aof,修复之后,可以正常重启
aof重写规则
Redis发布订阅
消息发送者 ---》 频道 ---》 消息订阅者
复杂的场景使用mq
Redis主从复制
环境配置
info replication
修改配置文件
端口 pid名字 log文件名字 dump.rdb名字
配置一主二从
默认情况下,每个redis服务都是主机,所以只需要配置从机
slaveof 127.0.0.1 6379 配置完之后可以使用info replication来查看信息,包括主机信息和当前角色名字
使用命令配置主从是暂时的,真实的主从配置应该在配置文件中进行配置
细节:
主机可以写,从机不能写,只能读,主机中的所有数据,都会自动被从机保存,从机进行写操作的时候会报错
测试:
1、主机关闭,查看从机状态,发现两个从机依旧是从机,只能进行读操作,当主机重新启动后,写入操作可以正常同步到从机
2、从机关闭,主机进行写操作,从机重启,发现写操作没有同步到从机,使用info replication指令查看,发现从机变成了主机,这是因为使用命令行配置的从关系是暂时的,这个时候,使用命令再次将这个“从机”变为真正的从机,会发现,之前主机的写操作同步过来了
复制原理
比如主机从机都处于正常状态的时候,主机进行写操作,从机同步,这个就是增量复制
层层链路
这种也可以完成主从复制,主机断开后,从机中依旧没有主机,80依旧不能进行写操作
哨兵模式出来之前,都是手动进行修改,slaveof no one 让自己变成主机,其他的从机可以手动连接到最新的主节点
如果80执行slaveof no one命名,就会成为主节点,81还是80的从节点,但是如果这个时候79恢复工作了,他就没有从机了
哨兵模式
自动选举主机
配置哨兵模式
创建文件sentinel.conf
# sentinel monitor 被监控的名字 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
后面的数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机
启动哨兵
redis-sentinel kconfig/sentinel.conf
如果master节点断开了,这个时候就会从从机中随机选择一个服务器(这里有一个投票算法)
failover 故障转移
sdown 挂掉,主机转移到。。。
如果主机恢复了,只能成为新主机的从机,这就是哨兵模式的规则
哨兵所有的配置项
Redis缓存穿透和雪崩
服务的高可用问题
缓存容易出现的问题
缓存穿透 查不到
解决方案
缓存击穿 量太大,缓存过期
缓存雪崩
声明:截图为狂神的笔记,供自己学习,如有不妥,我删了还不行嘛
补充:
公司项目部署过程中,使用到了redis 3.2.100版本,3.2版本之后redis需要设置密码,并且默认绑定的是本机地址,127.0.0.1,说白了,就是98服务器上部署之后,有一部分服务放在了42上,42上的服务访问不了98服务器的redis,这个时候需要再配置文件中将bind改成0.0.0.0,关闭保护模式,并且设置访问密码。