赞
踩
Redisopen in new window 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,Redis 存储的是 KV 键值对数据。
Redis 5.0 新增加的一个数据结构 Stream 可以用来做消息队列,Stream 支持:
(1)类型上
从类型上来说,mysql是关系型数据库,redis是缓存数据库
(2)作用上
mysql用于持久化的存储数据到硬盘,功能强大,速度较慢,基于磁盘,读写速度没有Redis快,但是不受空间容量限制,性价比高
redis用于存储使用较为频繁的数据到缓存中,读取速度快,基于内存,读写速度快,也可做持久化,但是内存空间有限,当数据量超过内存空间时,需扩充内存,但内存价格贵
(3)需求上
mysql和redis因为需求的不同,一般都是配合使用。
需要高性能的地方使用Redis,不需要高性能的地方使用MySQL。存储数据在MySQL和Redis之间做同步。
Cache Aside Pattern(旁路缓存模式)
Read/Write Through Pattern(读写穿透)
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 db,从而减轻了应用程序的职责。(很少用这种策略)
在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
Write Behind Pattern(异步缓存写入)
Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 db 的读写。但是,两个又有很大的不同:Read/Write Through 是同步更新 cache 和 db,而 Write Behind 则是只更新缓存,不直接更新 db,而是改为异步批量的方式来更新 db。
底层实现主要依赖这 8 种数据结构:简单动态字符串(SDS)、LinkedList(双向链表)、Hash Table(哈希表)、SkipList(跳跃表)、Intset(整数集合)、ZipList(压缩列表)、QuickList(快速列表)。
以业务比较简单的购物车场景举例
用户添加商品就是往 Hash 里面增加新的 field 与 value;查询购物车信息就是遍历对应的 Hash;更改商品数量直接修改对应的 value 值(直接 set 或者做运算皆可);删除商品就是删除 Hash 中对应的 field;清空购物车直接删除对应的 key 即可。
sorted set 的数据结构经常被用在各种排行榜的场景
使用 Set 实现
SPOP key count : 随机移除并获取指定集合中一个或多个元素,适合不允许重复中奖的场景。
SRANDMEMBER key count : 随机获取指定集合中指定数量的元素,适合允许重复中奖的场景。
Bitmap 使用日期(精确到天)作为 key,然后用户 ID 为 offset,如果当日活跃过就设置为 1。
SETBIT 20210308 2 1
HyperLogLog 是用来做基数统计的算法, 将访问指定页面的每个用户 ID 添加到 HyperLogLog 中。
哈希和跳跃表,
hash就是关联元素value和权重score
跳跃表就是给value排序
底层数据结构就是0/1bit 的二进制数值
ZipList就是当【zset】和【hash】容器对象在元素个数较少或元素长度较短时采用的数据结构。它是一块连续的内存空间,每一个元素都前后挨着,中间没有内存空隙。同时它也是一个经过特殊编码的双向链表,它的设计目标就是为了提高内存存储效率,
ZipList可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的,而不是编码成字符串序列。它能以O(1)的时间复杂度在表的两端提供push和pop操作
第一层是双向链表,会有多层来作为链表的索引。
二叉查找树的时间复杂度是O(logn),空间复杂度是O(n);跳表的时间复杂度是O(log_{k}n),k为跳表索引步长,空间复杂度是O(n)
引入多线程主要是为了提高网络 IO 读写性能
Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了,执行命令仍然是单线程顺序执行。因此,你也不需要担心线程安全问题。
Redis6.0 的多线程默认是禁用的,只使用主线程。如需开启需要设置IO线程数 > 1,需要修改 redis 配置文件 redis.conf :
因为内存是有限的,如果缓存中的所有数据都是一直保存的话,分分钟直接 Out of memory。
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间
过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。
在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里
Redis 提供了两个命令来生成 RDB 快照文件:
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
Redis 4.0 **开始支持 RDB 和 AOF 的混合持久化(**默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。
组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。
如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚
Redis 事务在运行错误的情况下,除了执行过程中出现错误的命令外,其他命令都能正常执行。并且,Redis 是不支持回滚(roll back)操作的。因此,Redis 事务其实是不满足原子性的(而且不满足持久性)。
你可以将 Redis 中的事务就理解为 :Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。
Redis 从 2.6 版本开始支持执行 Lua 脚本,它的功能和事务非常类似。我们可以利用 Lua 脚本来批量执行多条 Redis 命令,这些 Redis 命令会被提交到 Redis 服务器一次性执行完成,大幅减小了网络开销。
定义
缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。缓存服务宕机也会导致缓存雪崩现象,导致所有的请求都落到了数据库上
解决方案
设置不同的失效时间比如随机设置缓存的失效时间。
缓存永不失效(不太推荐,实用性太差)。
设置二级缓存。
在分布式系统中,一致性指多副本问题中的数据一致性
先更新数据库,后更新缓存
先更新缓存,后更新数据库
先更新数据库,后删除缓存
先删除缓存,后更新数据库
更新缓存
优点:每次数据变化都及时更新缓存,所以查询时不容易出现未命中的情况。
缺点:更新缓存的消耗比较大。如果数据需要经过复杂的计算再写入缓存,那么频繁的更新缓存,就会影响服务器的性能。如果是写入数据频繁的业务场景,那么可能频繁的更新缓存时,却没有业务读取该数据。
删除缓存
优点:操作简单,无论更新操作是否复杂,都是将缓存中的数据直接删除。
缺点:删除缓存后,下一次查询缓存会出现未命中,这时需要重新读取一次数据库。从上面的比较来看,一般情况下,删除缓存是更优的方案。
无论上面我们采用哪种方式去同步缓存与数据库,在第二步出现失败的时候,都建议采用重试机制解决
采用多主多从,每一个分区都是由一个Redis主机和多个从机组成,片区和片区之间是相互平行的。Redis Cluster集群采用了P2P的模式,完全去中心化。
一致性hash是一个0到2的32次方的闭合环型结构
系统的每个节点分配一个token,范围一般在0 ~ 2^{32} ,这些toke构成一个哈希环,数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点。
答题公式:多少个槽+原理+节点对槽的分配+优势
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
master节点的slave节点不分配槽,只拥有读权限
集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么节点 A 包含 0 到 5500号哈希槽,节点 B 包含5501 到 11000 号哈希槽,节点 C 包含11001 到 16384号哈希槽。
一致性哈希增加和移除节点需要rehash
Redis Cluster保证高可用主要还是依靠:故障检测与故障转移两种策略
min-slaves-to-writer 1
min-slaves-max-lag 10
表示至少有1个slave的与master的同步复制延迟不能超过10s。因此可以降低min-slaves-max-lag参数的值
16384
分布式锁是为了保证在分布式场景下,共享资源在同一时刻只能被同一个线程访问,或者说是用来控制分布式系统之间同步访问共享资源。
互斥性: 在任意时刻,同一条数据只能被一台机器上的一个线程执行
高可用性: 当部分节点宕机后,客户端仍可以正常地获取锁和释放锁
独占性: 加锁和解锁必须同一台服务器执行,不能再同一个服务器上加锁,在另外一个服务器上释放锁
防锁超时: 如果客户端没有主动释放锁,服务器会在一定时间后自动释放锁,防止客户端宕机或者网络异常宕机
基于关系型数据库
基于Redis
基于zookeeper
SETNX该命令的作用是当key不存在时设置key的值,当key存在时,什么都不做
存在的问题:如果执行到执行业务时,业务代码突然出现异常,无法进行删除锁这一步,就会死锁
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。