Redis 怎么学?
2020-12-22 13:23:29 1 举报
AI智能生成
耕达互联网学院
作者其他创作
大纲/内容
其他NoSQL 数据库的比较
MongoDB
Hbase,Cassandra
ElasticSearch
事务
常用命令
MULTI
标记一个事务块的开始
EXEC
执行所有事务块内的命令
DISCARD
取消事务,放弃执行事务块内的所有命令。
UNWATCH
取消 WATCH 命令对所有 key 的监视
WATCH key [key ...]
监视一个(或多个) key ,如果在事务执行(EXEC)之前这个(或这些) key 被其他命令所改动,那么事务将被打断
一旦执行了EXEC,之前加的监控锁都会失效
相当于java锁机制,乐观锁
事务经历阶段
开始事务
命令入队
执行事务
只支持部分事务
编译(语法错误)时出错,那么全部失败(回滚)
执行时有错误,那么继续执行,失败的失效
好处:使得Redis内部更加简单,而且运行速度更快
应用场景
金融
批量
发布订阅
无法取代其他专门做消息中间件的地位
常用命令
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态。
PUBLISH channel message
将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern ...]]
退订所有给定模式的频道。
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel ...]]
指退订给定的频道。
Redis 客户端
RedisTemplate
关于spring-redis
连接池自动管理,提供了一个高度封装的“RedisTemplate”类
针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations
将事务操作封装,有容器控制
针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)
Redisson
集成了很多工业级的分布式缓存产品
Lettuce
Redis 支持最好
Jedis
简单易用
Redis数据持久化
两种持久化方式
AOF
概念:以日志形式记录每一次对redis的写命令,可以通过重复执行记录的命令来进行数据恢复
AOF的重写机制:AOF提供了重写机制,去除无用指令以及合并多条指令达到压缩的目的。
更小的文件也意味着更快的加载速率,重写不会阻塞redis
更小的文件也意味着更快的加载速率,重写不会阻塞redis
优点:
1.AOF默认一秒钟执行一次fsync操作,即使发生故障,也最多丢失那一秒钟没来得及写入日志的命令数据。
2.AOF对误操作有更强的容错性。由于AOF是逐条命令的记录,因此当发生灾难性的数据误操作时(比如清库),只要这个时候AOF还没有被重写(重写机制),先把redis停掉,然后把AOF文件拷贝出来,将最后的误操作命令删除(比如清库的FLUSHALL),然后用修改过的AOF做数据恢复即可。
1.AOF默认一秒钟执行一次fsync操作,即使发生故障,也最多丢失那一秒钟没来得及写入日志的命令数据。
2.AOF对误操作有更强的容错性。由于AOF是逐条命令的记录,因此当发生灾难性的数据误操作时(比如清库),只要这个时候AOF还没有被重写(重写机制),先把redis停掉,然后把AOF文件拷贝出来,将最后的误操作命令删除(比如清库的FLUSHALL),然后用修改过的AOF做数据恢复即可。
缺点:
1.AOF文件记录的更详尽,意味着文件占用空间大
2.AOF数据恢复的速度相对于RDB更慢
1.AOF文件记录的更详尽,意味着文件占用空间大
2.AOF数据恢复的速度相对于RDB更慢
RDB
概念:生成某个时刻的redis数据快照,恢复时,直接加载快照即可
优点:
数据恢复速度相当AOF更快
数据恢复速度相当AOF更快
缺点:
1.因为是某个时刻的快照,在这个时刻和下一个备份点之间插入的数据会丢失,不适用于对数据敏感的场景
2.RDB经常需要fork子进程来保存快照,创建的过程是阻塞的重量级操作。如果数据量过大,可能造成线上服务卡顿
1.因为是某个时刻的快照,在这个时刻和下一个备份点之间插入的数据会丢失,不适用于对数据敏感的场景
2.RDB经常需要fork子进程来保存快照,创建的过程是阻塞的重量级操作。如果数据量过大,可能造成线上服务卡顿
持久化的选择,官方推荐是RDB和AOF同时开启,如果系统可以容忍几分钟的数据丢失,可以只用RDB。不建议只用AOF,因为AOF加载较慢。
数据一致性
先操作 Redis,再操作数据库
问题焦点
如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据
延时双删策略
在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。具体步骤是:
1)先删除缓存
2)再写数据库
3)休眠500毫秒(根据具体的业务时间来定)
4)再次删除缓存。
那么,这个500毫秒怎么确定的,具体该休眠多久呢? 需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。 当然,这种策略还要考虑 redis 和数据库主从同步的耗时。最后的写数据的休眠时间:则在读数据业务逻辑的耗时的基础上,加上几百ms即可。比如:休眠1秒。
1)先删除缓存
2)再写数据库
3)休眠500毫秒(根据具体的业务时间来定)
4)再次删除缓存。
那么,这个500毫秒怎么确定的,具体该休眠多久呢? 需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。 当然,这种策略还要考虑 redis 和数据库主从同步的耗时。最后的写数据的休眠时间:则在读数据业务逻辑的耗时的基础上,加上几百ms即可。比如:休眠1秒。
先操作数据库,再操作 Redis
1、不做任何操作,等着Redis里的缓存数据过期后,自动从数据库同步最新的数据,此时最严重的数据不一致性周期就是在缓存过期的一段时间(考虑一下这个过期时间的范围);如果在这个时间段内,又有新的更新请求,也许这次就更新缓存成功了。
2、如果数据一致性要求比较高,那么 Redis 操作失败后,我们把这个操作记录下来,异步处理,用 Redis 的数据去和数据库比对,如果不一致,再次更新缓存确保缓存数据与数据库数据一致。
2、如果数据一致性要求比较高,那么 Redis 操作失败后,我们把这个操作记录下来,异步处理,用 Redis 的数据去和数据库比对,如果不一致,再次更新缓存确保缓存数据与数据库数据一致。
设置缓存的过期时间
最终一致性的解决方案
所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存
强一致性、弱一致性、最终一致性
概念
从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
最终一致性细分
因果一致性。
如果进程A通知进程B它已更新了一个数据项,那么进程B的后续访问将返回更新后的值,且一次写入将保证取代前一次写入。与进程A无因果关系的进程C的访问遵守一般的最终一致性规则。
读己之所写(read-your-writes)”一致性。
当进程A自己更新一个数据项之后,它总是访问到更新过的值,绝不会看到旧值。这是因果一致性模型的一个特例。
会话(Session)一致性。
这是上一个模型的实用版本,它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之所写”一致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统的保证不会延续到新的会话。
单调(Monotonic)读一致性。
如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回在那个值之前的值。
单调写一致性。
系统保证来自同一个进程的写操作顺序执行。要是系统不能保证这种程度的一致性,就非常难以编程了。
数据类型
基本数据类型
hash 哈希
string 字符串
set 集合
list 列表
zset 有序集合
高级类型
HyperLogLog 基数统计
bitmap
算法实现
高效统计-汉明重量
geo
Z阶曲线
Base32编码
底层原理源码分析
底层编码
String底层编码及源码分析
raw
embstr
int
List 底层设计及优化
链表实现和数组实现区别
ziplist
quicklist
Hash
hashtable
ziplist
Set
hashtable
intset
Zset
skiplist
跳表源码分析
时间复杂度分析
ziplist
Redis 核心源码
核心键值对 ReidsDB源码详解
Redis 5 大基本数据类型底层编码源码精讲
Redis 6.0多线程分派机制底源码分析
Redis 跳表树结构底层源码分析
Redis GEO 实现原理及源码分析
Redis BitMap 高效统计算法及O(1) 存取速度,动态扩容机制详解
Redis 6.0 客户端缓存实现原理
Redis IO 模型
Redis 应用场景及实战
分布式锁实战及源码分析
分布式锁
概念
线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
使用场景
线程间并发问题和进程间并发问题都是可以通过分布式锁解决的,但是强烈不建议这样做!因为采用分布式锁解决这些小问题是非常消耗资源的!分布式锁应该用来解决分布式情况下的多进程并发问题才是最合适的。
有这样一个情境,线程A和线程B都共享某个变量X。
如果是单机情况下(单JVM),线程之间共享内存,只要使用线程锁就可以解决并发问题。
如果是分布式情况下(多JVM),线程A和线程B很可能不是在同一JVM中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。
有这样一个情境,线程A和线程B都共享某个变量X。
如果是单机情况下(单JVM),线程之间共享内存,只要使用线程锁就可以解决并发问题。
如果是分布式情况下(多JVM),线程A和线程B很可能不是在同一JVM中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。
分布式锁的实现(Redis)
概念
分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息,这时候我们很容易就想到了Redis。首先我们要搭建一个Redis服务器,用Redis服务器来存储锁信息。
关键点
1、锁信息必须是会过期超时的,不能让一个线程长期占有一个锁而导致死锁;
2、同一时刻只能有一个线程获取到锁。
2、同一时刻只能有一个线程获取到锁。
redis命令
setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。
get(key):获得key对应的value值,若不存在则返回nil。
getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。
expire(key, seconds):设置key-value的有效期为seconds秒。
get(key):获得key对应的value值,若不存在则返回nil。
getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。
expire(key, seconds):设置key-value的有效期为seconds秒。
读写锁
电商秒杀LUA脚本解决超卖问题
关注,取关,共同关注,好友推荐
GEO 附近的人功能实现及原理源码分析
社交应用Feed功能实战
签到,连续签到统计
海量用户数据统计
Top N 积分排行榜
最新评论,热点数据缓存
BitMap在互联网产品中的应用实战
热key倾斜,BigKey发现与优化
分布式计数器/分布式ID生成
缓存与数据库一致性问题
缓存异常解决方案及淘汰策略选择
缓存雪崩
Redis 缓存穿透
分布式队列/组赛队列
Redis常见架构
Redis主从模式
Redis主从架构设计
Redis主从数据同步原理
Redis主从实现读写分离
Redis数据同步阻塞分析
Redis哨兵机制
选举原理的介绍
实现Redis环境的HA高可用
主观下线与客观下线的介绍
最佳实践:Spring与Redis哨兵模式集群实战
Raft协议
集群模式
Redis集群架构设计过程剖析,槽的概念和键槽的细节概述
分片hash算法
CRC16(key) mod 16384(redis使用)
一致性hash的缺点
一致性hash算法
一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,就是对2^32去模
假设有三台服务器部署集群,首先通过hash(服务器A的IP地址) % 2^32,确定他们在环上的位置。数据访问时: 将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器
优点:
这样删除一个服务器节点或者新增一个服务器节点影响的数据不再是全部数据
这样删除一个服务器节点或者新增一个服务器节点影响的数据不再是全部数据
未使用一致性hash原因
一致性哈希算法对于数据分布、节点位置的控制并不是很友好,而Redis Cluster的槽位空间是自定义分配的
集群新增和删除节点
新增节点
1.启动节点(主节点)
2.redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000将节点加入集群
3.执行redis-cli --cluster reshard 127.0.0.1:7000重新分配集群slot
4.新增节点8为节点7的从节点 redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7000 --cluster-slave --cluster-master-id ef1bcdb677b1c8f8c3d290a9b1ce2e54f8589835
2.redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000将节点加入集群
3.执行redis-cli --cluster reshard 127.0.0.1:7000重新分配集群slot
4.新增节点8为节点7的从节点 redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7000 --cluster-slave --cluster-master-id ef1bcdb677b1c8f8c3d290a9b1ce2e54f8589835
删除节点
1.先删除从节点再删除主节点,不然哨兵会执行故障转移
2.redis-cli --cluster del-node 127.0.0.1:7000 f24b935a50a788692479c6beaf7c556f6d082253 (7000代表的是集群) 后接删除的节点id
3.下线主节点的时候记得执行reshard,把slot分配给剩余节点
2.redis-cli --cluster del-node 127.0.0.1:7000 f24b935a50a788692479c6beaf7c556f6d082253 (7000代表的是集群) 后接删除的节点id
3.下线主节点的时候记得执行reshard,把slot分配给剩余节点
在节点变化过程中数据不会受到影响
优点:高可用,可扩展。横向扩容可支持海量数据
Gossip 协议详解
集群脑裂
Redis中执行lua
1:eval 脚本内容 key个数 key列表 参数列表
eg:eval 'return "hello" .. KEY[1] .. ARGV[1]' 1 redis world
返回 hello redisworld
2:evalsha
1:加载redis脚本,返回SHA1值
2:执行对应的SHA1值
避免每次发送脚本的开销,脚本常驻服务端复用
eg>1:script load "$(cat lua_get.lua)"
返回SHA1,比如abcde123
2:evalsha abcde123
lua实现对redis访问
redis.call,eg:redis.call("set","hello","world")
redis.pcall,和上述一致
区别:redis.call如果执行失败,那么脚本执行结束后会直接返回错误,则pcall会忽略错误继续执行脚本
优势
1:lua在redis中执行是原子执行的,不会插入其他命令
2:可以帮助开发运维同事创建/定制自己的命令,并且常驻在内存中
3:将多个命令一次性打包,减少网络开销
redis管理脚本
script load:加载脚本到内存
script exists sha1 .. :判断脚本是否已加载到内存
script flush :清除所有已加载到内存的脚本
script kill :杀掉正则执行的脚本
注意:1:redis提供lua-time-limit指定脚本执行超时时间,但是此时间只是向其他命令发送BUSY信号
注意:2:上述情况需要使用script kill杀掉脚本,但注意若脚本已执行过写操作,kill命令将不生效
Redis 6.0 新特性
Redis多线程源码
Redis ACLs 权限控制
Redis 客户端缓存
resp3.协议
String 类型字符匹配
无盘复制
服务端代理
0 条评论
下一页