Redis
2021-06-22 14:49:40 2 举报
AI智能生成
Redis
作者其他创作
大纲/内容
简介
<b><font color="#c41230">Re </font><font color="#16884a">di </font><font color="#31a8e0">s</font></b>(<b><font color="#c41230">Re</font></b>mote <b><font color="#16884a">Di</font></b>ctionary <b><font color="#31a8e0">S</font></b>erver)远程字典服务<br>
Redis是基于C语言编写的的kv键值对数据库
性能方面
每秒可读11万次<br>
每秒可写8万1千次
为什么Redis性能高?
Redis其实是单线程的,它基于内存操作,它的性能瓶颈其实是内存大小,频率,以及网络带宽<br>
而且并不是多线程的性能就一定高,cpu上下文切换也需要消耗性能,这种切换一旦过多,就会造成资源浪费
Redis的默认端口是6379(这个其实是因为作者把某个女星的姓名用九宫格打出来是6379)
安装Redis
windows下安装(不推荐)
在github上搜索Redis,下载zip压缩包,解压即可
找到解压后的文件
大概就是这样
双击Redis.server.exe打开Redis<br>
<b><font color="#fdb813">这个终端窗口不要关闭,不然服务就会被终止</font></b>
双击Redis-cl.exei测试
测试是否连接成功
测试存取值
Linux下安装(官方推荐)
下载安装包(Redis.io)<br>
发送到服务器的opt(软件一般都安装在这里)目录下
解压压缩包
编译需要环境支持,如果没有c++环境的先配置环境
yum install gcc-c++
进入Redis文件夹进行软件编译
输入make
输入make install
然后我们会在/usr/local/bin下发现我们已经安装好的Redis
接下来我们修改Redis的配置文件,改成后台运行
大概在11%的位置<br>
然后我们在/usr/local/bin下建立一个专门存放Redis配置文件的文件夹,因为Redis之后组集群会有很多配置文件
就像这样
测试Redis
开启并连接
关闭并退出
外部访问记得打开防火墙
初始Redis
Redis的数据库
Redis一共有16个数据库
如图
Redis的16个数据库是相互独立的,可以使用select index进行切换
如图
清空Redis数据
flushdb
清除当前数据库的数据
flushall
清空所有数据库的记录
Redis可以设置过期时间
如图
五大数据类型
String(就是类似java中的字符串操作)
基本字符串
设置值
set [key] [value]
取值
get [key]<br>
追加值
append [key] [value]
查看长度<br>
strlen [key]
截取字符串范围(闭区间)
getrange [key] [start] [end]
getrange [key] 0 -1就是完整字符串
替换(相当于replace)
setrange [key] [start] [new]
带过期时间的设置
setex [key] [seconds] [value]<br>
setex(set with expire)<br>
不存在设置
setnx [key] [value]<br>
如果不存在这个key,就存储
如果已经有了这个key,该操作无效
可以批量添加,并且是原子操作
批量添加记录
mset k1 v1 k2 v2 ...
浏览量类型的字符串
自增
incr view
自减
decr view
固定长度自增
incrby view [num]
固定长度自减
decrby view [num]
存储对象
set user:id:name xiaoming<br>
set user:id:age 20
List
本质
是个双向链表
允许存在重复元素
存元素
左存(头插)
lpush [list] [value]
右存(尾插)
rpush [list] [value]
移除元素
左取
lpop [list]
右取
rpop [list]
移除指定的元素
lrem [list] [num] [value]<br>移除 某list num数量个 值为value的节点元素
根据index操作
lindex [list] [index]<br>
获取list长度
llen [list]<br>
range操作
lrange [list] [start] [end]
trim操作(把截取作为新的list替代旧的)
ltrim [list] [start] [end]
判断list是否存在
exists [list]
替换节点值(把index下标的值用value替换,不存在就报错)
lset [list] [index] [value]<br>
插值(在value0 前 | 后 插入value1的值)<br>
linsert [list] [before | after] [value0] [value1]
Set(无序不重复集合)
添加记录
sadd [set] [member]
查看指定set的所有值
smembers [set]<br>
查看指定set的元素个数
scard [set]
移除指定set的指定值
srem [set] [member]
随机获取一个元素
srandmember [set]
随机获取num个元素
srandmember [set] [num]
随机移除一个元素
spop [set]
从oldset移动指定的元素到newset
smove [oldset] [newset] [member]<br>
找set1和set2中的差集
sdiff [set1] [set2]
找set1和set2中的交集(共同关注可以这样实现)
sinter [set1] [set2]<br>
找set1和set2中的并集
sunion [set1] [set2]
Hash
存值
hset [map] [key] [value]
批量存值
hmset [map] [k1] [v1] [k2] [v2] ...
取值
hget [map] [key]
批量取值
hmget [map] [k1] [k2] ...
获得所有的k-v
hgetall [map]
获得k-v键值对数量
hlen [map]
判断key是否存在
exists [map] [key]
只获得所有的key
hkeys [map]
只获得所有的value
hvals [map]
设置不存在的k-v键值对(如果没有就设置成功,如果已经存在就设置失败)
hsexnx [map] [key] [value]
Zset(带score的有序集合)
添加
zadd [set] [score][member]
批量添加
zadd [set] [score1] [member1] [score2] [member2] ...
移除
zrem [set] [member]
获得指定set的数量
zcard [set]<br>
按照score升序获得min到max区间的所有member
zrangebyscore [set] [min] [max]
按照score降序获得min到max区间的所有member
zrevrangebyscore [set] [min] [max]
带score查询
zrangebyscore [set] [min] [max] withscores
三种特殊数据类型
Geospatial(地理位置)<br>
底层实现是zset,我们可以使用相关命令
有效经度是-180到180
有效纬度是-85到85
添加地理位置
geoadd [key] [经度] [纬度] [名称] [经度] [纬度] [名称]..
geoadd city 116.39 39.91 beijing 121.48 31.40 shanghai 113.27 23.15 guangzhou 113.88 22.55 shenzhen
查看指定key的经纬度
geopos [key] [名称] [名称] ... <br>
geopos city beijing
查看指定key已有地点
通过zset命令实现
zrange [key] 0 -1
移除地理位置
zrem [key] [名称]
zrem city chengdu guangzhou
两地之间的距离
geodist [key] [地点1] [地点2] [ m | km | ft | mi ]
geodist city beijing shanghai km
以一点为中心(给出经纬度),找出指定距离为半径的圆内地点(附近的人)
georadius [key] [经度] [纬度] [半径] [单位] ...
georadius city 108 28 2000 km withcoord withdist count 2
以一点为中心(使用zset中的member),找出指定距离为半径的圆内地点(附近的人)
georadiusbymember city beijing 3000 km withcoord withdist count 2
根据经纬度获取一个哈希值
geohash [key] [地点] [地点] [地点] ...
距离越近,获得的哈希值越接近
Hyperloglog(基数计算)<br>
内存占用小,适用于uv浏览量统计,有极小的误差
通过hash函数映射,并不存储元素本身,所以无法查看指定key的已存入元素
添加
pfadd [key] [member] [member] ...
统计数量
pfcount [key]
合并多个集合形成一个新的集合
pfmerge [newkey] [key1] [key2] ...
Bitmap(位图,可以记录唯二状态的记录,按位操作)
添加操作
setbit [map] [ 0 | 1 ]
查询操作
getbit [map] [index]
统计操作
bitcount [map]
事务<br>
⭐Redis的事务不保证原子性
每次使用事务都需要手动开启,声明周期到执行或者放弃结束
开启事务
multi
命令入队
输入命令
放弃事务
discard
执行事务
exec
异常
命令有错(相当于编译异常)<br>
事务整体都不会有效
事务队列存在运行错误(运行时异常)<br>
有错误的命令不生效但是不影响事务中别的命令
可以使用watch做乐观锁操作(失败了就unwatch,然后重复操作,达到自旋效果)
SpringBoot整合
Jedis
新建项目,引入依赖
<pre style="background-color: rgb(43, 43, 43); font-family: "JetBrains Mono", monospace; font-size: 9.8pt;"><font color="#cfd0d2"> <dependency><br> <groupId>redis.clients</groupId> <br> <artifactId>jedis</artifactId><br> <version>3.2.0</version><br> </dependency></font><font color="#a9b7c6"><br></font></pre>
配置一下远程Redis
开启后台运行
开启保护模式
设置密码
重启Redis服务
打开redis-cli连接本地服务,需要输入auth 密码才能继续后续操作,不然没有权限
然后输入shutdown关闭服务
redis-server redisconfigs/redis.config打开服务
编写测试代码
<pre style="background-color: rgb(43, 43, 43); font-family: "JetBrains Mono", monospace; font-size: 9.8pt;"><font color="#cfd0d2">package com.xiaoye;<br><br>import redis.clients.jedis.Jedis;<br><br>/**<br> * @author 小也<br> * @create 2021/4/28 19:47<br> */<br>public class Test {<br><br> public static void main(String[] args) {<br> //万物皆对象,先弄个jedis的对象出来,构造函数为主机地址和端口号<br> Jedis jedis = new Jedis("8.140.12.96",6379);<br> //给密码,获取权限<br> jedis.auth("密码");<br> //测试是否成功连接,控制台输出PONG则连接成功<br> System.out.println(jedis.ping());<br><br> }<br>}</font><br></pre>
lettuce
springboot2.x就把底层的redis操作从jedis改成了lettuce,因为jedis是线程不安全的
通过 redisTemplate.getConnectionFactory().getConnection(); 获得connection对象操作
Redis持久化
为什么要进行持久化操作?
Redis是内存数据库,断电就会丢失所有数据,所以必须有持久化操作
两种持久化操作
rdb(redis database)默认开启
触发规则
save规则
flushall命令
退出redis
恢复rdb文件
把dump.rbd放在启动目录就可以了,redis启动时会自动检查
优点
适合大规模数据恢复<br>
对数据的完整性要求不高
缺点
需要一定的时间间隔操作,如果期间redis宕机,最后一次数据无法保存
fork子进程占用一定空间
aof(append only file)默认关闭
机制
记录每一次的写操作,数据恢复时重新运行这些命令,重构数据
开启方法
redis.conf中把appendonly改成yes
Redis发布订阅
可以做好友动态、聊天室等等
实际使用
先订阅频道
然后新开窗口往频道里发布内容
此时发现之前订阅了xiaoye这个频道的窗口自动监听了频道消息
Redis主从复制
主要作用
实现数据热备份,是数据持久化的另一种操作
故障恢复,当某一服务挂了后,可以从节点进行数据恢复<br>
负载均衡,主机写,从机读,分担负载<br>
高可用基石,主从复制是哨兵机制和集群的基础<br>
适用场景
单台Redis的最大使用内存不要超过20G<br>
建议至少一主二从的配置,<b><font color="#f384ae">一主一从哨兵机制会出错</font></b>
环境搭建
⭐Redis默认自己就是主库,所以我们只需要配置从库
查看当前库的信息
info replication
复制配置文件,redis.conf
修改配置文件
注释bind绑定ip
/bind搜索
端口
/port搜索
守护线程开启
/daemonize搜索<br>
pid修改
/pidfile搜索<br>
日志文件修改
/logfile搜索<br>
dbfilename修改<br>
/dbfilename搜索
以配置文件启动redis,查看后台进程
后台进程
配置从机,找老大
在从机中配置
上面认老大的slaveof是命令式的,一次性的,我们最好使用配置文件配置
复制原理<br>
从机一旦连接,就会向主机发送一个sync同步命令,主机就会发送全部数据给从机,完成同步<br>
从机连接成功后会继续复制主机新增/改的值
哨兵模式
机制
哨兵进程检测redis服务进程,会间隔进行心跳检测确定redis服务进程是否存活
一旦主机挂机了,就会进行故障转移---failover,重新选取主机
就算挂掉的主机回来了,也只能作为从机继续服务了
使用
编写sentinel.conf
sentinel monitor [名称] <b><font color="#f384ae">127.0.0.1(主机地址)</font></b> <b><font color="#0076b3">6379(主机端口) </font><font color="#c41230">1(开启主机选举)</font></b>
启动哨兵进程
redis-sentinel sentinel.conf
主机挂掉后
哨兵机制会在下次心跳检测到主机挂掉,故障转移,选取新主机
之前的主机复活后
就算复活了,也只能当从机了,一旦失去不再来,除非当前主机挂掉重新选取才有机会
优点
基于主从复制,所有的主从复制的优点它都有
主从自动切换,故障可以转移,系统可用性更好<br>
缺点
不好在线扩容
哨兵模式的配置十分麻烦<br>
缓存穿透和雪崩
缓存穿透
现象
请求redis不存在的缓存数据,导致请求全部打到mysql数据库,形成缓存穿透
例子
恶意攻击
解决方案<br>
布隆过滤器
把请求存起来,存空
缓存击穿
现象
某个key非常热点,承担了超高并发,当这个key失效,持续的超高并发请求就会达到mysql数据库上<br>
例子
微博热搜宕机
解决方案
设置热点数据永不过期
加互斥锁
缓存击穿
现象
大量请求在缓存中失效,全部打进mysql数据库
例子
缓存时间过期,或者redis宕机
解决方案
多设置几台redis服务器
限流降级,保证服务可用<br>
设置缓存时间随机,失效均匀
0 条评论
下一页