Redis 官网
redis中文官方网站 中文网
windows环境安装使用
1、下载windows版本后解压
2、双击redis-server.exe,启动服务
3、双击redis-cli.exe,启动客户端
4、执行ping命令,返回PONG则代表成功
Linux环境安装使用
1、在官网下载Linux版本,并解压到linux服务器,使用root权限,进入解压目录
2、yum install gcc-c++ 安装gcc环境(若已有gcc环境,则直接进入第4步)
3、make
4、make install
5、默认安装在/usr/local/bin下
6、cd /usr/local/bin
7、mkdir config 在/usr/local/bin下创建配置文件
8、cp /home/mylinux/Redis/redis-6.0.6/redis.conf . 复制配置文件到config下
9、redis默认不是后台启动的,需修改配置文件
10、修改daemonize属性为yes(默认是no,需修改为使用守护进程方式运行)
11、启动redis服务,redis-server redis.conf
12、启动redis客户端,redis-cli
13、ps -ef | grep redis 查看redis进程
14、关闭redis服务 (kill -9 进程号)或(在客户端使用shuidown)
Redis
1、内存存储,断电即失,需要做持久化(rdb、aof),将内存中的数据保存到磁盘
2、效率高,可以用于高速缓存
特性
多样的数据类型
持久化
集群
事务
yum install gcc
gcc -v 查看版本
Redis是单线程的
Redis是基于内存操作的,CPU不是Redis的性能瓶颈,其瓶颈是机器的内存和网络带宽,既然可以使用单线程实现,就使用单线程了。
Redis默认有16个数据库,默认使用第0个数据库,可以使用select进行切换
指令
ping 指令后相应 PONG则代表启动成功
select 0 切换到默认数据库
select 1 切换到第一个数据库·
dbsize 查看数据库的使用大小
flushdb 清空当前库
flushall 清空所有数据库
keys * 查看所有的key值
dbsize 查看key的个数
exists key判断key值是否存在
move key 删除key键值对
set key value 将value值存储到key中
get key 获取key对应的value值
expire key 3 设置key3秒后过期
ttl key 查看key还有多久过期
type key 查看当前key的类型
数据类型
String
append key thisvalue 在可以值原value后追加thisvalue,若原key不存在,则相当于新建key
strlen key 查看key的value长度
GETRANGE key startnum endnum 截取key的子字符串,为左右闭区间
setrange key 2 XX 将第2位替换为XX
setex key 6 value 设置key的值为value,6秒后过期
setnx key value 当key不存在时,设置key为value
mset k1 v1 k2 v2 k3 v3 批量设置key value
mget k1 k2 k3 批量查看key的值
msetnx k1 v1 k4 v4 这是一个原子性操作,一起成功或一起失败
Int
incr key 对key值加一
decr key 对key值减一
incrby key num 对key加num
decrby key num 对key减num
getset key value 先获取值,然后设置新的value值,常用作更新方法
List
LPUSH list a 向头部放入a
RPUSH list a 向尾部放入a
LRANGE list 0 -1 查看list
lpop list 移除头部元素
rpop list 移除尾部元素
lindex list 0 查看list的第0个元素
llen list 查看list的长度
ltrim list 1 2 从1开始截取两个元素
rpoplpush list newlist 移除最后一个元素,并移动到新列表中
lset list 0 value 更新列表第0位为value
linsert list before value value1 在value前插入value1
Set
sadd set value 将value放入set中
smembers set 查看set中的元素
sismember set value 判断set中是否存在value值
scard set 查看set的长度
srem set value 从set中移除value的值
srandmember set 2 从set中随机取出2个值
spop 随机弹出删除一个元素
smove set newset value 将set中的value移动到newset中
sdiff set1 set2 取set1和set2的差集
sinter SET1 SET2 取SET1和SET2的交易
SUNION SET1 SET2 取SET1和SET2的并集
Hash哈希类型
Map集合,key-map类型
hset hash key value 将key-value格式的map存储到hash中
hget hash key 取出value
hmset hash key1 value1 key2 value2 设置多个map的存储
hmget hash key1 key2 获取多个键值对的值
hgetall hash 获取hash中的所有值
hkeys hash 获取hash中所有的key值
hvals hash 获取hash中所有的value值
hdel hash key 删除hash中的key
hlen hash 查看hash的长度
hexists hash key 判断hasn中是否存在key
Zset有序集合
zadd zset 1 value1 会按照1、2的顺序排序
zadd zset 2 value2
zrange zset 0 -1 查看所有的value值
zrem zset value 删除value
zcard zset 获取集合个数
Geospatial地理位置
可以推算地理位置,两地之间的距离等。
geoadd cityList 经度 纬度 cityname 添加cityname的地理位置
geopos cityList city 获取指定城市的经纬度
geodist cityList city1 city2 km 查看city1和city2之间的距离
m-米,km千米,mi英里,ft英尺
georadius cityList 经度 纬度 100 km 以这个经纬度为中心,查找附近100km内的坐标
georadius cityList 经度 纬度 100 km withdist 显示到中心距离的位置
georadius cityList 经度 纬度 100 km withcoord 显示他人的定位信息
georadius cityList 经度 纬度 100 km withdist withcoord count 2 只显示两条数据
georadiusbymember citylist city 100 km 查找以city城市为中心,附近100km
geohash citylist city1 city2 返回两个城市二维经纬度转为一维的11位hash串,两个字符串越接近,距离就越近
是基于zset进行封装的
zrange citylist 0 -1 查看所有保存的城市
zrem citylist city 从citylist中删除指定city元素
Hyperloglog基数统计
基数:不重复的元素
有0.81%的错误率,目的是为了统计
优点:占用的内存是固定的,只占用12kb的内存
pfadd key a b c d 将a、b、c、d放到key集合中
pfcount key 查看集合中元素的数量
pfmerge keynew key1 key2 取key1和key2的去重并集放到key中
BItmaps位图
setbit key 0 1 设置第0位为1
setbit key 1 1 设置第1位为1
getbit key 0 查看第0位的值
bitcount key 查看值为1的位的总数
事务
Redis单条命令具有原子性,要么同时成功,要么同时失败,但是Redis事务不保证原子性
在事务执行过程中,会有一次性、顺序性、排他性。
所有命令在事务中,没有被执行,只有发起执行命令的时候才会执行。
开启事务multi
命令入队
执行事务exec
discard 取消事务,取消事务中的所有命令
若命令代码有问题,则事务中所有的命令都不会被执行
若运行时问题,则其它命令可以正常执行,例:对string类型执行自增
乐观锁
watch key 监控key,相当于一个乐观锁
unwatch 放弃监控
若key发生改变,则该事务执行失败
watch key multi 写入关于key的语句 exec
Jedis(Java使用redis的中间件)
采用的直连,多线程操作是不安全的
Jedis jedis = new Jedis(ip,prot); 连接redis
jedis.close(); 关闭连接
jedis.set(key,value); //存储值
.... 其余使用命令和上述相同
Springboot集成redis
使用spring-data-redis包
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.6.0</version> </dependency>
@Autowired RedisTemplate redis; redis.opsForValue() //操作字符串格式 redis.opsForList() //操作list redis.opsForSet() //操作Set //获取redis的连接对象,也可以通过redis连接对象处理 RedisConnection conn = redisTemplate.getConnectionFactory().getConnection(); conn.flushDb();
持久化
RDB持久化(RedisDatabase)
在指定时间间隔内将内存中的数据集快照写入磁盘,它的恢复是将快照文件直接读取到内存中。
Redis会单独创建一个子进程进行持久化,将数据先写入到一个临时文件中,待持久化过程结束了,再用这个文件替换上次持久化好的文件。
缺点:在最后一次持久化时,可能会丢失数据
触发规则
save规则满足,会自动触发dump.rdb文件
执行flushall命令,会自动触发dump.rdb文件
AOF(Append Only File)
以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来。
默认不开启,需要手动开启,将appendonly no 修改为yes
如果aof被破坏,则redis会无法启动,需要使用redis-check-aof 去修复文件(redis-check-aof --fix appendonly.aof)
优点:
每次修改都会同步,文件的完整性更好
每秒同步一次,可能会丢失1秒的数据
缺点:
aof效率比rdb低
Redus发布订阅
订阅端:
subscribe title //订阅title,就开始进行监听
发送端:
publish title titleMessage //发布title信息为titleMessage,在订阅端就可以看到发布的信息
Redis主从复制
指将一台Redis主节点服务器的数据,复制到从节点服务器。数据的复制是单向的,只能由主节点到从节点复制。
每台主节点可以有多个从节点,一个从节点只能有一个主节点
主从复制,读写分离,80%情况下都是读操作,为了减缓服务器压力,一主二从。
单台Redis的内存建议不超过20G
环境配置
info replication 查看信息
role:master 代表角色为master
connected_slaves:0 代表没有从机
单机多集群修改:
1、端口
2、pid
3、logfile
4、dump.rdb
然后启动服务
配置主从复制
默认情况下,每台服务器都是主节点,一般只需要配置从机即可
slaveof 127.0.0.1 6379 在6380端口客户端下执行,将6380设置为6379的从机(通过命令配置是暂时的,正常应该使用配置文件配置)
配置文件配置:replicaof ip port 将当前服务器配置为从节点
主机负责写操作,从机只能读取操作
原理:
slave从机启动成功连接到master主机后,会发送一个sync同步命令
master接到sync命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集指令,在后台进程执行结束后,master将传送整个数据文件到slave,并完成一次完全同步。
只要重新连接到master,一次完全同步(全量)将被自动执行
主机宕机后手动配置主机
若主节点断开,在从机上可以使用slaveof no one设置为主节点
哨兵模式(自动选取主节点)
哨兵配置文件sentinel.conf
port port 设置哨兵运行的端口
sentinel monitor redisname 127.0.0.1 6379 1 //1代表当1个哨兵认为master主节点失联,那么重新选取主节点
启动哨兵监控
redis-sentinel sentinel.conf
如果master节点断开后,就会从从节点中随机选一个节点作为主节点
若主机断开后重新连接,此时原主机也只能变为一个从机。
Redis缓存穿透和雪崩
缓存穿透(大面积查不到)
当用户查询一个数据时,先去redis中查询,若redis中没有,这时候就会查询MySQL数据库。当用户量很大时,缓存都没有命中,于是都去查询持久层数据库,就对数据库造成了很大压力,就出现了缓存穿透。
解决方案
1、布隆过滤器
2、缓存空对象
缓存击穿(对某个key查询量太大,缓存过期)
当某个key特别热门,大并发集中对这个key进行访问,在这个key失效的瞬间持续的大并发会穿破缓存,直接请求数据库。
解决方案
1、设置热点数据永不过期
2、加互斥锁(分布式锁)