赞
踩
使用 C 语言开发的数据库,不过与传统数据库不同的是 Redis 的数据是存在内存中,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。除了缓存之外,Redis 也经常用来做分布式锁,甚至是消息队列。
渐进式Rehash
当哈希表存储巨大数量键值对,如果一次rehash,可能宕机
步骤:
这样避免了集中rehash大计算量造成问题,将计算均摊到每个字典增删查改操作。
过期字典(hash表),key为数据库的键,value是long long类型整数,保存了key指向的数据库键的过期时间。
过期的贪心策略:
如果数据一直没有被选择清除掉,而且也没有访问的惰性清除,将会一直占用内存,所以需要数据淘汰策略防止内存不够用。
在redis.conf中的maxmemory-policy中进行配置
如果没有设置expire,那么在volatile的表现和noeviciton一致。
传统的lru和lfu使用链表实现,按使用时间排序,淘汰最久的。redis则不维护队列,而是从key中随机选择n个,然后淘汰最久的,为了提高效率。
缓存和数据库中都没有的数据,用户不断请求,导致数据库压力过大,一半是攻击,解法:
缓存中没有,数据库中有点数据,并发量太大情况下,数据库压力过大,解法:
缓存同一时间大量失效,使得请求都堆积到数据库中,导致数据库崩掉,解法:
如果对数据有强一致性要求,不能放缓存。缓存中只能保证最终一致性,一般先更新数据库,再删除缓存。
保证这个顺序的原因是如果先删缓存那么如果有请求过来又会把旧值缓存。
如果一定要先删缓存,那么需要使用延时双删,先缓存,再数据库,过段时间再删缓存。
Redis的性能瓶颈主要来自于内存和网络而不是操作,引入目的是提高网络IO性能,即多线程只在网络耗时上操作,执行命令仍然采用单线程。
异步IO模式,当IO完成之后,回调对应的函数进行处理。
Redis基于Reactor模式开发了自己的网络事件处理器,被称为文件事件处理器。
实现一个redis线程处理多个IO流的效果。
快照和只追加文件
增量备份,记录每次对服务器写的操作,服务器重启时会重新执行这些命令恢复原始数据。
更安全,效率更低。实时性较好,已成为主流方案。
默认不开启,如果开启要修改配置文件
appendonly yes
每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘的AOF文件。
三种策略控制系统冲洗AOF的频率
特点
定时快照存储,在指定时间间隔对数据进行快照存储。
在指定时间间隔(也可以手动触发)将内存中数据集快照写入磁盘,创建子进程写入临时文件dump.rdb,父进程可以做别的事,生成完成之后覆盖原来的快照
在执行AOF重写操作时,按如下原则处理
结合两种方式的优点,RDB的快速恢复能力和AOF的丢失数据窗口。
共同点:两者都是基于内存的数据库,一般都是当作缓存使用。
区别:
Redis | Memcached | |
---|---|---|
数据类型 | 丰富的数据类型 list set等 | 只支持key-value |
持久化 | 支持将硬盘保存到磁盘 | 将数据全部存储在内存中 |
内存用尽 | 内存使用完可以转移到磁盘或者淘汰 | 内存使用完会报错 |
线程 | 单线程 | 多线程 |
集群 | 支持cluster模式 | 没有原生集群模式,依靠客户端往集群中分片写入数据 |
memcached在线程方面较Redis有优势,所以不考虑持久化和复杂数据结构的情况下,可以使用memcached。
一个master拥有多个slave,主从复制不会阻塞,master可以继续处理客户端命令。
优点:读写分离,分载主节点压力
缺点:
基于主从模式,引入哨兵来监控和自动处理故障。监控master和slave是否正常运行(ping),当多个哨兵发现主节点没有反应的时候,自动选出slave作为master。
下线模式
优缺点
主从模式和哨兵模式下,每个redis节点都存储相同数据,耗费资源。
cluster下将数据分成一万多个槽,计算公式为slot=CRC16(key)&16383,分配保存到互为主从的节点上。每个节点都是互相连接的,会保存自己与其他节点的信息。数据先写到主节点,再同步到从节点,读取数据时,输入key不在当前节点上,则指向正确节点。
操作步骤:
三种只能使用全量复制的情况:
setnx命令返回整数值,为1成功,0失败。
一般不能直接用其实现分布式锁,因为可能死锁,需要设定自动过期时间,而过期时间和设置命令不是原子的,redis改进了set命令,增加了nx选项,启用该选项的效果就会和setnx一样了。
setnx key value
setnx key value expire key seconds
set key value nx ex seconds
解锁
del key
加锁需要给锁设置标识,进程只能释放自己的锁,结合lua脚本编排命令
# 加锁
set key random-value nx ex seconds
# 解锁
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。