【数据库】 - 队列,缓存, Redis, MemCache
2024-12-06 11:26:45 0 举报
AI智能生成
数据库,键值数据库,检索数据库,数据结构,数据排序,索引; 数据库实例分析 - mysql, mongodb, redis, elasticsearch (es) 涵盖各类关系/非关系型数据库。
作者其他创作
大纲/内容
缓存类型介绍
本地缓存
内存缓存
LRU缓存策略
FIFO缓存策略
LFU缓存策略
磁盘缓存
文件缓存
db本地数据库缓存
SSD缓存
分布式缓存
Redis缓存
数据持久化
主从复制
集群模式
Memcached缓存
LRU替换算法
哈希分布
多线程处理
其他分布式缓存
Couchbase
Cassandra
MongoDB
缓存应用场景
中间结果缓存
MapReduce中间结果
Spark中间结果
数据预处理缓存
数据清洗缓存
数据转换缓存
数据缓存
用户数据缓存
商品数据缓存
页面缓存
静态页面缓存
动态页面缓存
一致性
强一致性
同步更新
事务支持
弱一致性
最终一致性
异步更新
非关系型(键值)数据库
Redis
Redis的应用场景
缓存
会话缓存(Session Cache)
全页缓存(FPC)
队列
数据存储
排行榜/计数器
发布/订阅
Redis的安装
ubuntu command
sudo apt update
sudo apt isntall -y redis
sudo apt install redis-tool
sudo apt install redis-server
Redis的集群架构
主从架构
1 master - n salve
方案
从服务器连接主服务器,发送SYNC命令;
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;(从服务器初始化完成)
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;(从服务器初始化完成)
优点
Master 主机会自动将数据同步到从机,可以进行读写分离
Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据
缺点
Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题
哨兵架构
1 master - n slave - n sentinel
方案
哨兵的作用就是监控Redis系统的运行状况。它的功能包括以下两个。
(1)监控主服务器和从服务器是否正常运行。
(2)主服务器出现故障时自动将从服务器转换为主服务器。
(1)监控主服务器和从服务器是否正常运行。
(2)主服务器出现故障时自动将从服务器转换为主服务器。
优点
哨兵模式是基于主从模式的,所有主从的优点,读写分离,非阻塞数据同步。
可以自动切换,系统更健壮,可用性更高。
缺点
水平扩容仍然比较困难,只能通过增加集群物理性能来垂直扩容
分片集群
(master - slave) * n
方案
Redis-Cluster采用无中心结构,它的特点如下:
(1) 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
(2) 节点的fail是通过集群中超过半数的节点检测失效时才生效。
(1) 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
(2) 节点的fail是通过集群中超过半数的节点检测失效时才生效。
优点
无中心架构;数据按照key的 hash slot 存储分布在多个节点,节点间数据共享实现水平扩容
可扩展性:可线性扩展到 1000 多个节点,节点可动态添加或删除;
高可用性:部分节点不可用时,集群仍可用。
缺点
Key 事务操作支持有限,只支持多 key 在同一节点上的事务操作,当多个 Key 分布于不同的节点上时使用事务困难。
Key 作为数据分区的最小粒度,不能将一个很大的键值对象如 hash、list 等映射到不同的节点。
集群管理
CLUSTER NODES:显示集群中所有节点的信息。
CLUSTER INFO:显示集群的信息,如节点数量、槽位分配等。
CLUSTER KEYSLOT <key>:返回指定键被分配到的槽位。
CLUSTER SLOTS:显示集群中所有槽位的分配情况。
CLUSTER COUNTKEYSINSLOT <slot>:返回指定槽位中的键数量。
CLUSTER MEET <ip> <port>:将一个新节点添加到集群中。
CLUSTER REPLICATE <node_id>:将一个节点设置为另一个节点的从节点。
CLUSTER FAILOVER:手动触发故障转移,将主节点切换为从节点。
CLUSTER FORGET <node_id>:从集群中移除指定节点。
CLUSTER FLUSHSLOTS:清空集群中所有槽位的分配信息。
CLUSTER INFO:显示集群的信息,如节点数量、槽位分配等。
CLUSTER KEYSLOT <key>:返回指定键被分配到的槽位。
CLUSTER SLOTS:显示集群中所有槽位的分配情况。
CLUSTER COUNTKEYSINSLOT <slot>:返回指定槽位中的键数量。
CLUSTER MEET <ip> <port>:将一个新节点添加到集群中。
CLUSTER REPLICATE <node_id>:将一个节点设置为另一个节点的从节点。
CLUSTER FAILOVER:手动触发故障转移,将主节点切换为从节点。
CLUSTER FORGET <node_id>:从集群中移除指定节点。
CLUSTER FLUSHSLOTS:清空集群中所有槽位的分配信息。
Redis数据类型
String
存储的值
可以是字符串、整数或浮点,统称为元素
读写能力
对字符串操作,对整数类型加减
String类型操作 [key|value(string/int/float)]
set
设置置顶key的值
set key value
get
获取指定key的值
get key
incr
将key中储存的数字值增一
incr key
decr key
将key中储存的数字值减一
decr key
incrby
key 所储存的值增加给定的减量值(decrement)
incrby key decrement
decrby
key 所储存的值减去给定的减量值(decrement)
decrby key decrement
append
如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
append key value
setnx
只有在 key 不存在时设置 key 的值
setnx key value
mget
获取所有(一个或多个)给定 key 的值。
mget key [key...]
mset
同时设置一个或多个 key-value 对
mget key value [key value ...]
getset
将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
getset key value
setex
将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
setex key seconds value
strlen
返回 key 所储存的字符串值的长度
strlen key
del
删除键
del key
List
存储的值
一个有序序列集合且每个节点都包好了一个元素
读写能力
序列两端推入、或弹出元素、修剪、查改或移除元素
List类型操作
[key => value1 | 自
value2 | 左
value3 | 而
value4 | 右]
[key => value1 | 自
value2 | 左
value3 | 而
value4 | 右]
push
lpush
将一个或多个值插入到列表头部
lpush key value1 [value2....]
rpush
将一个或多个值插入到列表尾部
rpush key value1 [value2....]
pop
lpop
移出并获取列表的第一个元素
lpop key
rpop
移出并获取列表的最后一个元素
rpop key
lrange
获取列表指定范围内的元素
lrange key start stop
llen
获取列表长度
llen key
lindex
通过索引获取列表中的元素
lindex key index
lrem
移除列表元素
lrem key count value
count > 0
从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT
count < 0
从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值
count = 0
移除表中所有与 VALUE 相等的值
lset key index value
通过索引设置列表元素的值
lset key index value
Set
存储的值
无序的方式,各不相同的元素
读写能力
从集合中插入或删除元素
Set类型操作
key->[ value1
value2
value3
value4]
key->[ value1
value2
value3
value4]
sadd
向集合添加一个或多个成员(存在则返回0)
sdd key member1 [member2]
scard
获取集合的成员数
scard key
sinter
返回给定所有集合的交集
sinter key1 [key2]
sismember
判断 member 元素是否是集合 key 的成员
sismember key member
smembers
返回集合中的所有成员
smembers key
srandmember
返回集合中一个或多个随机数
srandmember key [count]
srem
移除集合中一个或多个成员
srem key member1 [member2]
Hash
存储的值
有key-valued的散列组,其中key是字符串,value是元素
读写能力
按照key进行增加删除
Hash类型操作
key-> key1 value(string/int/float)
key2 value(string/int/float)
key3 value(string/int/float)
key4 value(string/int/float)
key-> key1 value(string/int/float)
key2 value(string/int/float)
key3 value(string/int/float)
key4 value(string/int/float)
hset
将哈希表 key 中的字段 field 的值设为 value
srem key field value
hmset
同时将多个 field-value (域-值)对设置到哈希表 key 中
hmset key field1 value1 [field2 value2]
hsetnx
只有在字段 field 不存在时,设置哈希表字段的值
hsetnx key field value
hget
获取存储在哈希表中指定字段的值
hget key field
hmget
获取所有给定字段的值
hget key field1 [field2]
hgetall
获取在哈希表中指定 key 的所有字段和值
hgetall key
hvals
获取哈希表中所有值
hvals key
hlen
获取哈希表中字段的数量
hlen key
hkeys
获取所有哈希表中的字段
hkeys key
hdel
删除一个或多个哈希表字段
hdel key field1 [field2]
hexitst
查看哈希表 key 中,指定的字段是否存在
hexitst key field
Sort Set
存储能力
带分数的score-value有序集合,其中score为浮点,value为元素
读写能力
集合插入,按照分数范围查找
Sorc Set类型操作
key-> score(10.1) value(string/int/float) rank:1
score(9.1) value(string/int/float) rank:0
score(11.2) value(string/int/float) rank:2
key-> score(10.1) value(string/int/float) rank:1
score(9.1) value(string/int/float) rank:0
score(11.2) value(string/int/float) rank:2
zadd
向有序集合添加一个或多个成员,或者更新已存在成员的分数
zadd key score1 member1 [score2 member2....]
zcard
获取有序集合的成员数
zcard key
zcount
计算在有序集合中指定区间分数的成员数
zcount key min max
zincrby
有序集合中对指定成员的分数加上增量 increment
zincrby key increment member
zrange
通过索引区间返回有序集合成指定区间内的成员
zrange key start stop [withscores]
zrank
返回有序集合中指定成员的索引
zrank key member
zrem
移除有序集合中的一个或多个成员
zrem key member1 [member2....]
zrevrange
返回有序集中指定区间内的成员,通过索引,分数从高到底
zrevrange key start stop [withscores]
zscore
返回有序集中,成员的分数值
zscore key member
Redis数据持久化
RDB
RDB 是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘。
自动触发
在 redis.conf 配置文件中的 SNAPSHOTTING 下
手动触发
执行save、bgsave命令
优势
1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
缺点
1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,如果不采用压缩算法(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。
2、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)
2、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)
AOF
AOF 则是通过保存Redis服务器所执行的写命令来记录数据库状态。
触发配置
在 redis.conf 配置文件的 APPEND ONLY MODE 下
优势
①、AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
②、AOF 文件使用 Redis 命令追加的形式来构造,因此即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 也很容易修正 AOF 文件。
③、AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。
②、AOF 文件使用 Redis 命令追加的形式来构造,因此即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 也很容易修正 AOF 文件。
③、AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。
缺点
①、对于具有相同数据的的 Redis,AOF 文件通常会比 RDF 文件体积更大。
②、虽然 AOF 提供了多种同步的频率,默认情况每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时 RDB 比 AOF 具好更好的性能保证。
③、RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG
②、虽然 AOF 提供了多种同步的频率,默认情况每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时 RDB 比 AOF 具好更好的性能保证。
③、RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG
Redis中的数据查询
单节点中查询
KEYS key_name
KEYS key_name_pattern*
SCAN cursor [MATCH pattern] [COUNT count]
SCAN 0 MATCH "user:*" COUNT 10
集群节点查询
CLUSTER INFO:显示集群的信息,如节点数量、槽位分配等。
CLUSTER NODES:显示集群中所有节点的信息。
CLUSTER KEYSLOT key_name 命令来获取某个key所在的槽位
CLUSTER KEYSLOT baidu
return int
CLUSTER GETKEYSINSLOT slot_num key_nums 命令获取该槽位上的所有key
CLUSTER GETKEYSINSLOT 150 10
return list
CLUSTER COUNTKEYSINSLOT slot 返回指定槽位中的键数量。
MemCache
MemCache的应用场景
缓存数据库查询结果
提升Web应用性能
减少数据库访问次数
缩短响应时间
在高并发环境下稳定系统
分散请求压力
防止数据库过载
缓存静态内容
加速网页加载
缓存HTML/CSS/JS文件
减少服务器带宽消耗
实现内容分发网络(CDN)功能
跨地域内容加速
提高用户访问体验
分布式会话管理
共享用户会话信息
在集群环境中保持会话一致性
支持用户无缝切换服务器
会话失效控制
设置会话超时时间
自动清理过期会话
临时数据存储
存储临时计算结果
避免重复计算
提高计算效率
消息队列功能
实现任务分发
支持异步处理
MemCache的安装
在Linux系统上安装
下载MemCache安装包
访问MemCache官方网站
选择适合的版本
编译并安装MemCache
安装依赖库
执行编译命令
配置MemCache服务
创建配置文件
设置启动参数
在Windows系统上安装
使用Windows安装包
下载Windows安装包
运行安装程序
配置MemCache服务
创建服务项
设置服务参数
通过命令行安装
下载MemCache源码
使用Cygwin编译
MemCache的配置
内存分配
设置最大内存使用量
根据服务器内存大小调整
避免内存溢出
内存碎片整理
启用内存碎片整理功能
定期清理内存碎片
连接管理
设置最大连接数
根据应用需求调整
防止连接过多导致性能下降
连接超时控制
设置连接超时时间
自动关闭空闲连接
日志记录
启用日志记录功能
记录MemCache运行状态
便于故障排查
设置日志级别
选择适当的日志级别
避免日志过多影响性能
安全配置
设置访问密码
防止未授权访问
提高MemCache安全性
网络访问控制
限制访问IP地址
防止恶意攻击
MemCache的使用
基本操作
添加数据到缓存
使用set命令
指定数据过期时间
从缓存中获取数据
使用get命令
检查数据是否存在
删除缓存数据
使用delete命令
清空整个缓存
字符串(String):通常用于存储简单的文本数据。
例:存储用户的名字、某个缓存页面的 HTML 内容等。
示例:mc.set('username', 'john_doe')
示例:mc.set('username', 'john_doe')
整数(Integer):用于存储整数,可以用作计数器等。
例:存储访问量、点赞数等。
示例:mc.set('user_id', 12345)
示例:mc.set('user_id', 12345)
布尔值(Boolean):存储 True 或 False 的值,用于表示状态。
例:存储用户是否已登录、功能是否开启等。
示例:mc.set('is_active', True)
示例:mc.set('is_active', True)
字典(Dictionary):存储复杂的 JSON-like 数据结构,通常用于存储对象信息。
例:存储用户信息、产品详情等。
示例:mc.set('user_data', {'name': 'John', 'age': 30})
示例:mc.set('user_data', {'name': 'John', 'age': 30})
列表(List):存储一组数据,通常用于存储排序的数据。
例:存储用户得分、活动日志等。
示例:mc.set('user_scores', [98, 85, 92])
Memcached的持久化特性
没有持久化机制:Memcached 不会将数据写入磁盘,也不会保持数据的持久性。如果 Memcached 进程停止或崩溃,缓存中的所有数据都会丢失。
内存存储:数据完全存储在内存中,这使得 Memcached 非常快速,但也意味着它只能存储临时数据。它并不适合存储需要长期保存或必须持久化的数据。
缓存失效:Memcached 提供了 过期时间(TTL,time-to-live)设置,缓存的数据会在过期时间后自动失效并被删除。如果没有过期时间设置,则缓存的数据会根据内存空间被逐出(LRU,最少使用的算法)。
Memcache的内存管理机制
Slab Allocator
Slab Allocator的定义
Slab Allocator的作用
Slab Class
Slab Class的定义
Slab Class的组成
Slab Class的作用
Chunk
Chunk的定义
Chunk的作用
Chunk的大小
内存分配策略
按Slab需求分配Page
各Slab按需使用Chunk存储
内存分配的特点
数据过期方式
LRU算法
Laxzy Expiration
其他过期方式
缓存优化策略
缓存预热
主动预热
定时任务预热
启动预热
被动预热
请求触发预热
访问频率触发预热
缓存击穿
互斥锁
单线程处理
超时控制
布隆过滤器
快速判断是否存在
降低误判率
缓存雪崩
随机过期时间
避免集中过期
分散过期时间
二级缓存
备份缓存
延迟加载
缓存降级
读降级
降级为读数据库
降级为读旧数据
写降级
异步写
写日志
Redis是单进程的吗?
是的,Redis 是一个单进程的应用程序。它使用事件驱动模型(Event-Driven Model),通常通过多路复用技术(如select或epoll)在一个线程中处理多个客户端的请求。由于是单进程的,Redis 本身并发处理的方式是通过事件循环来管理多个客户端的请求,而不是使用多线程或多进程。
数据一致性主要通过持久化(RDB 和 AOF)、主从复制、分布式集群等方式保证,但 Redis 本身并不提供强一致性,而是采用最终一致性模型。
Redis 的事务机制提供了单进程内的原子性保证,但不支持复杂的分布式事务。
Redis 的事务机制提供了单进程内的原子性保证,但不支持复杂的分布式事务。
Redis的效率会不会很低?
高效的内存操作
Redis 是基于内存的数据存储,所有的数据都保存在内存中,读写操作非常迅速,能够在纳秒级别处理请求。
Redis 采用单线程(即单进程)
设计来避免并发锁的问题。多线程通常会引入上下文切换的开销;
单线程模型的另一个优点是 避免了锁竞争。
内存数据结构
Redis 提供多种高效的数据结构(如 字符串、哈希、列表、集合、有序集合等);
这些数据结构都经过精心设计,优化了内存访问速度。特别是在处理大数据量时,Redis 的表现仍然非常出色。
Redis 提供多种高效的数据结构(如 字符串、哈希、列表、集合、有序集合等);
这些数据结构都经过精心设计,优化了内存访问速度。特别是在处理大数据量时,Redis 的表现仍然非常出色。
事件驱动与 I/O 多路复用
Redis 使用 I/O 多路复用 技术(如 epoll 或 select),它能在单线程中同时处理多个客户端请求。这种方式能够充分利用 CPU 时间片,实现高效的并发处理。通过事件循环,Redis 可以在收到大量请求时,尽量减少等待 I/O 操作的时间,保持高吞吐量和低延迟。
Redis 使用 I/O 多路复用 技术(如 epoll 或 select),它能在单线程中同时处理多个客户端请求。这种方式能够充分利用 CPU 时间片,实现高效的并发处理。通过事件循环,Redis 可以在收到大量请求时,尽量减少等待 I/O 操作的时间,保持高吞吐量和低延迟。
MemCache的性能对比Redis
性能对比总结:
Memcached 和 Redis 都非常高效,但 Memcached 专注于简单的键值对存储,并且经过高度优化,通常在非常 简单的缓存场景 下会有 更低的延迟。
Redis 提供了更多的功能和数据结构支持,虽然这些特性可能导致某些操作的开销稍大,但在处理复杂的数据结构(如列表、集合、哈希)时,Redis 的效率依然非常高。
Memcached 和 Redis 都非常高效,但 Memcached 专注于简单的键值对存储,并且经过高度优化,通常在非常 简单的缓存场景 下会有 更低的延迟。
Redis 提供了更多的功能和数据结构支持,虽然这些特性可能导致某些操作的开销稍大,但在处理复杂的数据结构(如列表、集合、哈希)时,Redis 的效率依然非常高。
结论:
如果只需要处理简单的 键值对缓存,Memcached 可能会略有优势,尤其是在高并发的场景下。
如果需要处理更复杂的数据结构或其他高级功能(如事务、持久化、消息队列等),Redis 更为合适。
如果只需要处理简单的 键值对缓存,Memcached 可能会略有优势,尤其是在高并发的场景下。
如果需要处理更复杂的数据结构或其他高级功能(如事务、持久化、消息队列等),Redis 更为合适。
0 条评论
下一页