Redis
2021-11-21 13:23:41 1 举报
AI智能生成
redis学习总结
作者其他创作
大纲/内容
默认16分数据库,类似数组下标0开始,默认适用0号库
redis 单线程+多路IO复用技术
基础介绍
keys * 查看当前库所有key
exists key 判断key 是否存在
type key 查看你的key是什么类型
del key 删除指定的key 数据
unlink key 根据value 选择非阻塞删除
expire key 10 10秒钟之后key 过期
ttl key 查看还有多少秒过期, -1 表示永不过期 -2 表示已过期
select 编号 选择指定数据库
dbsize 查看当前数据库的key 的数量
flushdb 清空当前库
flushall 通杀全部库
关闭:redis-cli -p port shutdown
常用命令
二进制安全
一个value 最多可以存储512MB
set <key> <value> [nx、xx、ex、px]
get <key>:查询对应的值
append <key><value>:将给定的<value>追加到原值的末尾
strlen<key> :获取值长度
setnx<key><value>:key 不存在时设置key值
incr<key>将key 中纯村的数字增1,只对数字值操作,如果为空新增值为1
decr<key>:将 key 中储存的数字值减1,只对数字值操作,如果为空新增值为-1
incrby / decrby <key><步长>将 key 中储存的数字值增减。自定义步长。
mset <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value对
mget <key1><key2><key3> .....同时获取一个或多个 value
msetnx <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
getrange <key><起始位置><结束位置>获得值的范围,类似java中的substring,前包,后包
setrange <key><起始位置><value>用 <value> 覆写<key>所储存的字符串值,从<起始位置>开始(索引从0开始)。
setex <key><过期时间><value>设置键值的同时,设置过期时间,单位秒。
getset <key><value>以新换旧,设置了新值同时获得旧值。
数据结构:SDS 简单动态字符串,采取预分配冗余空间的方式来减少内存的频繁分配,capacity实际分配的空间一般高于实际长度 len ,
字符串
简介:单键多值
数据结构:双向链表,ziplist ,数据比较多时是quicklist
1、lpush/rpush <key><value1><value2><value3> .... 从左边/右边插入一个或多个值
2、lpop/rpop <key>从左边/右边吐出一个值。值在键在,值光键亡。
3、rpoplpush <key1><key2>从<key1>列表右边吐出一个值,插到<key2>列表左边。
4、lrange <key><start><stop>按照索引下标获得元素(从左到右)
5、lrange mylist 0 -1 0左边第一个,-1右边第一个,(0-1表示获取所有
6、lindex <key><index>按照索引下标获得元素(从左到右)
7、llen <key>获得列表长度
8、linsert <key> before <value><newvalue>在<value>的后面插入<newvalue>插入值
9、lrem <key><n><value>从左边删除n个value(从左到右)
10、lset<key><index><value>将列表key下标为index的值替换成value
列表list
简介:存储无重复的列表数据,提供了可以判断某个成员是否在一个set集合内的重要数据
是string类型的无序集合,低层是一个value 为null 的hash表
add <key><value1><value2> ..... 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
smembers <key>取出该集合的所有值。
sismember <key><value>判断集合<key>是否为含有该<value>值,有1,没有0
scard<key>返回该集合的元素个数。
srem <key><value1><value2> .... 删除集合中的某个元素。
spop <key>随机从该集合中吐出一个值。
srandmember <key><n>随机从该集合中取出n个值。不会从集合中删除 。
smove <source><destination>value把集合中一个值从一个集合移动到另一个集合
sinter <key1><key2>返回两个集合的交集元素。
sunion <key1><key2>返回两个集合的并集元素。
sdiff <key1><key2>返回两个集合的差集元素(key1中的,不包含key2中的)
dict 字典,字典是用hash表实现的
数据结构:
集合set
简介:键值对集合
String类型的field和value的映射表
hset <key><field><value>给<key>集合中的 <field>键赋值<value>
hget <key1><field>从<key1>集合<field>取出 value
hmset <key1><field1><value1><field2><value2>... 批量设置hash的值
hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在。
hkeys <key>列出该hash集合的所有field
hvals <key>列出该hash集合的所有value
hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 1 -1
hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在 .
Hash 类型数据对应的数据结构是两种:ziplist,hashtable,当field-value 长度比较短且个数比较少时,使用ziplist,否则使用hashtable
hash
简介:与set去表时每个成员都关联了一个评分(score),这个评分被用来按照从最低到最高分的方式排序集合中的成员。集合的成员是唯一,但是评分可以重复
zadd <key><score1><value1><score2><value2>…
将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
zrange <key><start><stop> [WITHSCORES] 返回有序集 key 中,下标在<start><stop>之间的元素带WITHSCORES,可以让分数一起和值返回到结果集。
zrangebyscore key minmax [withscores] [limit offset count]返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
zrevrangebyscore key maxmin [withscores] [limit offset count] 同上,改为从大到小排列。
zincrby <key><increment><value> 为元素的score加上增量
zrem <key><value>删除该集合下,指定值的元素
zcount <key><min><max>统计该集合,分数区间内的元素个数
zrank <key><value>返回该值在集合中的排名,从0开始。
hash,hash 的作用是关联元素value 和权重score ,保障元素value 的唯一性,可以通过元素value罩都熬响应的score值
跳跃表,目的在于给元素value 排序,根据score 的范围获取元素列表
底层使用了两个数据结构
分层
跳跃表:
数据结构
有序set
数据类型
.###Units单位### :只支持byte 不区分大小写
.###INCLUDES包含###:多实例配置可以把公用文件提取出来
bind:接受ip访问(d)
.protected-mode
port:6379
tcp-backlog
timeout 0 表示永不关闭
tcp-keepalive 客户端的一种心跳检测
daemonize 是否为后台进程
pidfile 存放pid文件的位置,每个实例产生一个不同的pid文件
locglevel:日志级别
logfile 日志文件名称
databases 16
.###网络相关配置 ###
设置密码
###SECURITY安全###
maxclients 默认10000
maxmemorty 建议必须设置,否则内存占满导致宕机
volatile-lru:使用LRU算法移除key,只对设置了过期时间的键;(最近最少使用)
allkeys-lru:在所有集合key中,使用LRU算法移除key
volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
allkeys-random:在所有集合key中,移除随机的key
volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
noeviction:不进行移除。针对写操作,只是返回错误信息
maxmemory-policy:移除规则
设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小,redis默认会检查这么多个key并选择其中LRU的那个。
一般设置3到7的数字,数值越小样本越不准确,但性能消耗越小。
maxmemory-samples
.#### LIMITS限制 ###
.###GENERAL通用###
redis.conf
配置介绍
客户端可以订阅任意数量的频道
1、打开一个客户端订阅channel1:SUBSCRIBE channel1
打开另一个客户端,给channel1发布消息hello publish channel1 hello
3、打开第一个客户端可以看到发送的消息
命令:
发布订阅模式
(1)Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。(2)Bitmaps单独提供了一套命令, 所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。
1、setbit(1)格式setbit<key><offset><value>设置Bitmaps中某个偏移量的值(0或1)
2、getbit(1)格式getbit<key><offset>获取Bitmaps中某个偏移量的值
bitcount统计字符串被设置为1的bit数。一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,start、end 是指bit组的字节的下标数,二者皆包含。
4、bitop(1)格式bitop and(or/not/xor) <destkey> [key…]
命令
bitMaps
(1)数据存储在MySQL表中,使用distinct count计算不重复个数
(2)使用Redis提供的hash、set、bitmaps等数据结构来处理
解决基数问题有很多种方案:
结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的
每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
1、pfadd (1)格式pfadd <key>< element> [element ...] 添加指定元素到 HyperLogLog 中
2、pfcount(1)格式pfcount<key> [key ...] 计算HLL的近似基数,可以计算多个HLL,比如用HLL存储每天的UV,计算一周的UV可以使用7天的UV合并计算即可
3、pfmerge(1)格式pfmerge<destkey><sourcekey> [sourcekey ...] 将一个或多个HLL合并后的结果存储在另一个HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得
HyperLogLog
使用:经纬度设置,查询,范围查询,距离查询,经度纬度hash
1、geoadd(1)格式geoadd<key>< longitude><latitude><member> [longitude latitude member...] 添加地理位置(经度,纬度,名称)
2、geopos (1)格式geopos <key><member> [member...] 获得指定地区的坐标值
3、geodist(1)格式geodist<key><member1><member2> [m|km|ft|mi ] 获取两个位置之间的直线距离
4、georadius(1)格式georadius<key>< longitude><latitude>radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素
Geospatial
新数据类型
key
String
List
zset
Jedis API
Jedis操作
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- spring2.X集成redis所需common-pool2--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version></dependency>
#Redis服务器地址spring.redis.host=192.168.140.136#Redis服务器连接端口spring.redis.port=6379#Redis数据库索引(默认为0)spring.redis.database= 0#连接超时时间(毫秒)spring.redis.timeout=1800000#连接池最大连接数(使用负值表示没有限制)spring.redis.lettuce.pool.max-active=20#最大阻塞等待时间(负数表示没限制)spring.redis.lettuce.pool.max-wait=-1#连接池中的最大空闲连接spring.redis.lettuce.pool.max-idle=5#连接池中的最小空闲连接spring.redis.lettuce.pool.min-idle=0
结合spring boot
Redis事务的主要作用就是串联多个命令防止别的命令插队。
从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。组队的过程中可以通过discard来放弃组队。
分支主题
组队失败 exec 会失败,组队成功,exec有成功有失败
Multi、Exec、discard
组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。
如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
事务错误处理
悲观锁:行锁,表锁,读锁,写锁,操作之前先上锁
观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
乐观锁
WATCH key [key ...]
取消 WATCH 命令对所有 key 的监视。
如果在执行 WATCH 命令之后,EXEC 命令或DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。http://doc.redisfans.com/transaction/exec.html
unwatch
单独的隔离操作 事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
没有隔离级别的概念 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
不保证原子性 事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
三大特性:
Redis的事务定义
redis 事务 锁机制 秒杀
在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里
Redis会单独创建(fork)一个子进程来进行持久化
RDB的缺点是最后一次持久化后的数据可能丢失。
流程
在redis.conf中配置文件名称,默认为dump.rdb
触发策略:save 3600 1 3600 秒中至少一个key发生变化
save :save时只管保存,其它不管,全部阻塞。手动保存。不建议。bgsave:Redis会在后台异步进行快照操作, 快照同时还可以响应客户端请求。可以通过lastsave 命令获取最后一次成功执行快照的时间
stop-writes-on-bgsave-error
rdbcompression 压缩文件,LZF算法进行压缩
相关配置:.###SNAPSHOTTING快照###
rdb备份步骤
适合大规模的数据恢复对数据完整性和一致性要求不高更适合使用节省磁盘空间恢复速度快
优势:
劣势:
动态停止RDB:redis-cli config set save ""#save后给空值,表示禁用保存策略
如何停止
RDB
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
客户端的请求写命令会被append追加到AOF缓冲区内;
AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;
Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;
持久化流程
默认不开启:可以在redis.conf中配置文件名称,默认为 appendonly.aof AOF文件的保存路径,同RDB的路径一致。
修改默认的appendonly no,改为yes将有数据的aof文件复制一份保存到对应目录(查看目录:config get dir)恢复:重启redis然后重新加载
正常恢复
修改默认的appendonly no,改为yes如遇到AOF文件损坏,通过/usr/local/bin/redis-check-aof--fix appendonly.aof进行恢复 恢复:重启redis,然后重新加载备份被写坏的AOF文件
异常恢复
AOF启动/修复/恢复
appendfsync always始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
appendfsync everysec每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
AOF同步频率
备份机制更稳健,丢失数据概率更低。可读的日志文本,通过操作AOF稳健,可以处理误操作。
优势
比起RDB占用更多的磁盘空间。恢复备份速度要慢。每次读写都同步的话,有一定的性能压力。存在个别Bug,造成恢复不能
劣势
AOF
用哪个好官方推荐两个都启用。如果对数据不敏感,可以选单独用RDB。不建议单独用 AOF,因为可能会出现Bug。如果只是做纯内存缓存,可以都不用。
Redis 持久化:同时启动rdb,aof 默认取aof
主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主
是什么
读写分离,性能扩展容灾快速恢复
能干嘛
slaveof <ip><port>:成为某个实例的从机
info replication:查看主从复制信息
主机写,从机读,从机读会报错
主机挂掉,重启一切ok
从机挂掉,重启需要重设:slaveof ip port
slave-priority 10:设置从机的优先级,值越小优先级越高,用于选举主机时使用,默认100
include /myredis/redis.confpidfile /var/run/redis_6379.pidport 6379dbfilename dump6379.rdb
怎么玩
slave数据的切入点:从头开始
从机是否可写:不可以
主机down后:从机原地等待
主机回来后:一切照旧
从机dawn机后回来需要重新slaveof ip port 数据照旧
问题:
一主二仆
数据同步与一仆二主一致
主->从(主)->从从
薪火相传
slaveof no one:当主机挂掉用 自动晋升为主
反客为主
复制原理:
常用的三招:
反客为主的自动版
1、调整为一仆二主模式
2、sentinel.conf
3、sentinel monitor mymaster 127.0.0.1 6379 1
4、执行redis-sentinel /myredis/sentinel.conf
关闭 主 哪个从机会被选举为主机呢?根据优先级别:slave-priority
原主机重启后会变为从机
复制延迟
哨兵模式
代码实现
Redis 主从复制:通过代理来解决主机ip发生变化
对redis的水平扩容,将整个数据库分布存储在这N个几点,每个节点存储总数据的1/N
集群通过分区来提供一定成都的可用性,
cluster-enabled yes 打开集群模式
cluster-config-file nodes-6379.conf 设定节点配置文件名
cluster-node-timeout 15000 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换。
redis cluster配置修改
配置:
一个集群至少要有三个主节点。(集群可用,需要集群可用的节点数大于集群总节点数的一半)选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上。
slot:16384: CRC16(key) % 16384 计算key 属于哪个插槽
集群合体redis-cli --cluster create --cluster-replicas 1 192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391
-c 采用集群策略连接
如果主节点下线?从节点能否自动升为主节点?注意:15秒超时
主节点恢复后,主从关系会如何?主节点回来变成从机。
cluster-require-full-coverage 为yes ,那么 ,整个集群都挂掉
而cluster-require-full-coverage 为no ,那么,该插槽数据全都不能使用,也无法存储。
如果所有某一段插槽的主从节点都宕掉
故障
多键操作不被支持
lua脚本不被支持
集群的缺点
Redis 集群模式:无中心化
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
对空值缓存
设置可访问白名单
采用布隆过滤器
进行实时监控
解决方案
缓存穿透
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
预先设置热门数据
实时调整
使用锁
缓存击穿
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
(1)构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)
(2)使用锁或队列:用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。不适用高并发情况
(3)设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际key的缓存
(4)将缓存失效时间分散开:比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
缓存雪崩
缓存逻辑
Redis 应用问题解决
基于数据库实现分布式锁
1. 多个客户端同时获取锁(setnx)2. 获取成功,执行业务逻辑{从db获取数据,放入缓存},执行完成释放锁(del)3. 其他客户端等待重试
优化锁过期时间(节点挂了,不释放锁)
优化之UUID防误删
优化之lua脚本保证删除的原子性
基于缓存(redis等)
基于zookeeper
分布式锁
自由主题
Redis
收藏
收藏
0 条评论
下一页
为你推荐
查看更多