文章目录
- 一、主从复制
- 1.单例redis存在的问题
- 2.主从复制是什么?
- 3.主从复制的原理
- 4.主从搭建
- 1)准备工作
- 2)方式一
- 3)方式二
- 5.python中操作
- 1)原生操作
- 2)Django的缓存操作
- 二、Redis哨兵(Redis-Sentinel)
- 1.主从复制存在的问题
- 2.哨兵(Redis-Sentinel)
- 1)什么是哨兵
- 2)架构说明
- 3)搭建哨兵的目的
- 4)哨兵的主要工作任务
- 3.哨兵的搭建
- 4.配置文件解释
- 5.Python操作哨兵
- 三、Redis集群(Redis Cluser)
- 1.Redis集群介绍背景
- 1)主从与哨兵存在的问题
- 2)解决
- 2.数据分布(分布式数据库)
- 1)存在问题
- 2)分区方案
- 3.集群搭建
- 4.Python中操作redis集群
- 5.集群扩容
- 6.集群缩容
- 四、缓存更新策略
- 五、缓存穿透,缓存击穿,缓存雪崩
一、主从复制
1.单例redis存在的问题
'机器故障;容量瓶颈;QPS瓶颈'QPS瓶颈:主从 一主一从,写操作都写到主库,读操作从从库读容量瓶颈:集群机器故障:一主两从,哨兵故障转义
2.主从复制是什么?
'一主一从,一主多从'作用1 :做读写分离作用2 :做数据副本作用3 :提高并发量一个master(主库)可以有多个slave(从库)一个slave(从库)只能有一个master(主库)'数据流向是单向的,从master(主库)到slave(从库,只能读,不允许写数据)'
3.主从复制的原理
'主从复制的原理'1. 副本库(从库)通过slaveof 127.0.0.1 6379命令,连接主库,并发送SYNC给主库 2. 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库3. 副本库接收后会应用RDB快照4. 主库会陆续将中间产生的新的操作,保存并发送给副本库5. 到此,我们主复制集就正常工作了6. 再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的'那么主从复制要不要开启持久化'无论创不创建持久化,都可以开启主从,但是如果不开持久化,主库重启操作,会造成所有主从数据丢失!
4.主从搭建
1)准备工作
'启动两个redis-server的进程,来模拟两台机器的两个redis进程' ' 也可以多个从库,复制从库配置即可,修改端口和保存文件的文件夹即可'-准备两个配置文件'配置文件1'daemonize yesbind 0.0.0.0pidfile "/var/run/redis.pid"requirepass "1234" # 主库密码,redis最好设置密码 ,设置redis登录密码 这个看自己需求可以不要port 6379dir "/root/redis-7.2.4/data"logfile "6379.log"appendonly yesappendfilename "appendonly-6379.aof"appendfsync everysecno-appendfsync-on-rewrite yesaof-use-rdb-preamble yes-------------------------------'配置文件2'daemonize yesbind 0.0.0.0port 6380dir "/root/redis-7.2.4/data1"masterauth 1234 # 这里是主库的访问密码,主从认证密码,否则主从不能同步,这个看自己需求可以不要,如果不要就不能设置主库密码logfile "6380.log"appendonly yesappendfilename "appendonly-6380.aof"appendfsync everysecno-appendfsync-on-rewrite yesaof-use-rdb-preamble yes'注意:如果两个配置都没有密码的情况下,可以直接操作,设置那个为从库,然后从库执行命令即可''如果有密码的情况,必须提前设置从库,然后在从库中设置主库的访问密码才可以,我这里设置了密码,所以需要先设置'-启动两个进程(当前文件下)reids-server ./redis.confreids-server ./redis_6380.conf
2)方式一
-6379设置为主,6380设置为从-链接到从库,执行:slaveof 127.0.0.1 6379 # 异步,因为我是一台机器做的模拟,所以链接本地地址,如果不同机器就写设置主库的机器的ip地址和端口-info 可以查看主从关系-主从既能查,又能写-从库只能查-flushall # 清空库数据-断开主从关系(也是在从库执行命令):slaveof no one # 取消复制,不会把之前的数据清除'一旦断开关系,那么从断开那刻开始,从库将接收不到主库数据,但是断开之前的数据任然保留着'
3)方式二
通过配置文件min-slaves-to-write 1min-slaves-max-lag 3#在从服务器的数量少于1个,或者三个从服务器的延迟(lag)值都大于或等于3秒时,主服务器将拒绝执行写命令-核心配置通过配置文件slaveof 127.0.0.1 6379slave-read-only yes'这种方式一配置好,从库就已经有主库的数据了'
5.python中操作
1)原生操作
'原生操作'-主:10.0.0.111::6379-从:10.0.0.111::6380-从:10.0.0.111::6381'主库'conn=10.0.0.111::6379以后只 set mset rpush 操作'从库'conn1=10.0.0.111::6380conn2=10.0.0.111::6381只要是查询,随机从conn1和conn2中出10.0.0.111
2)Django的缓存操作
第一步:redis的配置中配置多个redisCACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://xxx.xxx.xxx.xxx:6379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},"redis1": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://xxx.xxx.xxx.xxx:6379/0","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}}}第二步:使用from django.core.cache import cachescaches['default'].set("name",'jack') # 写res=caches['redis1'].get('name') # 读
二、Redis哨兵(Redis-Sentinel)
1.主从复制存在的问题
主从复制存在的问题:'当主从复制中,有一主多从的情况下,如果主库发生故障,那么整个就会崩掉,因为需要解决这个问题,所以就需要用到哨兵'1 主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个slave变成master-使用哨兵来解决该问题2 主从复制,只能主写数据,所以写能力和存储能力有限-使用集群来解决该问题
2.哨兵(Redis-Sentinel)
1)什么是哨兵
在主从模式下(主从模式就是把下图的所有哨兵去掉),master节点负责写请求,然后异步同步给slave节点,从节点负责处理读请求。如果master宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源。这就无法达到高可用,而通过哨兵模式就可以解决这一问题。
哨兵模式是Redis的高可用方式,哨兵节点是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点
。 哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点挂掉时,哨兵会第一时间感知到,并且在slave节点中重新选出来一个新的master
,然后将新的master信息通知给client端,从而实现高可用。这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息。
2)架构说明
'可以做故障判断,故障转移,通知客户端(sentinal其实是一个进程),客户端直接连接sentinel的地址'1 多个sentinel发现并确认master有问题(内部已经帮你实现了)2 选举出一个sentinel作为领导(Raft算法(共识算法/选举算法))3 选取一个slave作为新的master4 通知其余slave成为新的master的slave5 通知客户端主从变化6 等待老的master复活成为新master的slave'哨兵只需要配置文件配置好,上面的操作,可以自动实现'
3)搭建哨兵的目的
一旦一主多从的架构,主库发生故障,能够自动转移一主多从架构的:高可用-redis服务对外高度可用-django服务项目是否是高可用的?-nginx的转发(负载解决)
4)哨兵的主要工作任务
(1)监控:哨兵会不断地检查你的Master和Slave是否运作正常。(2)通知提醒:当被监控的某个Redis节点出现问题时,哨兵可以通过 API 向管理员或者其他应用程序发送通知。(3)自动故障迁移:当一个Master不能正常工作时,哨兵会进行自动故障迁移操作,将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master;当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用新Master代替失效Master。
3.哨兵的搭建
哨兵配置步骤:'这里我就在一台机器上演示,做一主两从的(也可以搞更多都行)'(启动三个哨兵,也就会开启三个进程)-一台机器,启动三个sentinel1.先搭建一主两从的配置(跟上面搭建主从复制差不多的配置)# 记得得在当前路径下创建 data data1 data2 个文件夹,因为下面的配置文件中dir都需要一个文件夹'第一个是主库配置文件'daemonize yespidfile /var/run/redis.pidport 6379dir "/root/redis/data"logfile “6379.log”requirepass 1234 # 我配置的redis设置密码,再生产环境都是需要的'第二个是从库配置文件'daemonize yespidfile /var/run/redis2.pidport 6380dir "/root/redis/data1"logfile “6380.log”masterauth 1234 # 连接master密码,这里是主库的访问密码 '如果主库没有配置,就无需操作这个'slaveof 127.0.0.1 6379slave-read-only yes'第三个是从库配置文件'daemonize yespidfile /var/run/redis3.pidport 6381dir "/root/redis/data2"logfile “6381.log”masterauth 1234 # 连接master密码,这里是主库的访问密码slaveof 127.0.0.1 6379slave-read-only yes2.启动三个redis服务(后台启动)redis-server ./redis.confredis-server ./redis_6380.confredis-server ./redis_6381.conf3.三个Sentinel配置# sentinel.conf这个文件# 把哨兵也当成一个redis服务器创建三个配置文件分别叫sentinel_26379.conf sentinel_26380.conf sentinel_26381.conf#内容如下(需要修改端口,文件地址日志文件名字)'sentinel_26379.conf sentinel_26380.conf sentinel_26381.conf'-三个配置文件,改一下端口和dir即可port 26379daemonize yesdir ./dataprotected-mode nobind 0.0.0.0logfile "redis_sentinel3.log"sentinel auth-pass mymaster 1234 'redispass密码' # 连接master密码,如果主库有密码,就需要配置sentinel monitor mymaster 127.0.0.1 6379 2sentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 1800004.启动哨兵./src/redis-sentinel ./sentinel_26379.conf ./src/redis-sentinel ./sentinel_26380.conf ./src/redis-sentinel ./sentinel_26381.conf5.查看哨兵是否正常启动ps aux |grep redis # 可以看到有三个redis-server和三个哨兵6.哨兵,客户端也可以链接redis-cli -p 26379-info # 查看master0:name=mymaster,status=sdown,address=127.0.0.1:6379,slaves=2,sentinels=3集群名字叫:mymaster,状态ok,主库是:127.0.0.1:6379,有两个从库,哨兵有三个7.停止主库,启动哨兵,会故障转移,会从中选举一个从库,将之变成主库,而其他从库,复制现在的主库-kill -9 主库服务的进程号# 杀进程-pkill -9 redis # 批量杀,会把跟redis相关的都停止掉-停止一个从库,是不会做转移-即便原来的主库启动,它也是从库了
4.配置文件解释
配置文件解释
sentinel monitor mymaster 10.0.0.111 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000解释:
1.sentinel monitor mymaster:
-监控一个名为 mymaster 的主服务器,后面跟着主服务器的IP和端口,以及最少需要有多少个哨兵同意才进行故障转移。
-告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效2.sentinel down-after-milliseconds:
-如果一个服务器在指定的毫秒数内没有响应,则认为它是主观下线。
-这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒3.sentinel parallel-syncs:
-在故障转移期间,可以有几个从服务器同时进行同步。
-这个配置项指定了在发生主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成主备切换所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。4.sentinel failover-timeout: 故障转移超时时间
5.Python操作哨兵
'''python操作哨兵'''
import redis
from redis.sentinel import Sentinel'''连接哨兵服务器(主机名也可以用域名)'''
# 192.168.200.100
sentinel = Sentinel([('192.168.200.100', 26379),('192.168.200.100', 26380),('192.168.200.100', 26381)],socket_timeout=5)print(sentinel)# 获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)##### 读写分离
# 获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5)
w_ret = master.set('foo', 'bar')slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
r_ret = slave.get('foo')
print(r_ret)
三、Redis集群(Redis Cluser)
1.Redis集群介绍背景
1)主从与哨兵存在的问题
#1 主从---》提高并发量#2 哨兵----》高可用1 并发量:单机redis qps为10w/s,但是我们可能需要百万级别的并发量2 数据量:机器内存16g--256g,如果存500g数据呢?
2)解决
解决:加机器,分布式redis cluster 在2015年的 3.0 版本加入了,满足分布式的需求
2.数据分布(分布式数据库)
1)存在问题
假设全量的数据非常大,500g,单机已经无法满足,我们需要进行分区,分到若干个子集中
2)分区方案
分布方式 | 特点 | 产品 |
---|---|---|
哈希分布 | 数据分散度高,建值分布于业务无关,无法顺序访问,支持批量操作 | 一致性哈希memcache,redis cluster,其他缓存产品 |
顺序分布 | 数据分散度易倾斜,建值业务相关,可顺序访问,支持批量操作 | BigTable,HBase |
1.顺序分区原理:100个数据分到3个节点上 1--33第一个节点;34--66第二个节点;67--100第三个节点(很多关系型数据库使用此种方式)'数据分散度易倾斜,建值业务相关,可顺序访问,支持批量操作'2.哈希分区原理:hash分区: 节点取余 ,假设3台机器, hash(key)%3,落到不同节点上'数据分散度高,建值分布于业务无关,无法顺序访问,支持批量操作 一致性哈希memcache,redis cluster,其他缓存产品'节点取余分区:缺点:节点扩容,添加一个节点,存在问题,很多数据需要偏移,总偏移量要大于80%,推荐翻倍扩容,由3变成6,数据量迁移为50%,比80%降低一致性哈希分区客户端分片:哈希+顺时针(优化取余)节点伸缩:只影响临近节点,但是还有数据迁移的情况伸缩:保证最小迁移数据和无法保证负载均衡(这样总共5个节点,数据就不均匀了),翻倍扩容可以实现负载均衡虚拟槽分区(redis集群)预设虚拟槽:每个槽映射一个数据子集(16384个槽),一般比节点数大(redis集群不会超过16384台机器)良好的哈希函数:如CRC16服务端管理节点、槽、数据:如redis cluster(槽的范围0–16383)5个节点,把16384个槽平均分配到每个节点,客户端会把数据发送给任意一个节点,通过CRC16对key进行哈希对16383进行取余,算出当前key属于哪部分槽,属于哪个节点,每个节点都会记录是不是负责这部分槽,如果是负责的,进行保存,如果槽不在自己范围内,redis cluster是共享消息的模式,它知道哪个节点负责哪些槽,返回结果,让客户端找对应的节点去存服务端管理节点,槽,关系
3.集群搭建
'这里就演示,启动6个redis节点,一主一从架构 3个节点 存数据,每个有一个从库,做高可用'搭建步骤:1.第一步:写6个redis配置文件 (redis-7000 ------7005)i redis-7000.confport 7000daemonize yesdir "/root/redis-7.2.4/data/"logfile "7000.log"dbfilename "dump-7000.rdb"cluster-enabled yescluster-config-file nodes-7000.confcluster-require-full-coverage yes 2.第二步:快速生成剩余5个配置文件sed 's/7000/7001/g' redis-7000.conf > redis-7001.confsed 's/7000/7002/g' redis-7000.conf > redis-7002.confsed 's/7000/7003/g' redis-7000.conf > redis-7003.confsed 's/7000/7004/g' redis-7000.conf > redis-7004.confsed 's/7000/7005/g' redis-7000.conf > redis-7005.conf3.第三步;启动6个节点redis-server ./redis-7000.confredis-server ./redis-7001.confredis-server ./redis-7002.confredis-server ./redis-7003.confredis-server ./redis-7004.confredis-server ./redis-7005.conf4.第四步:搭建集群redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005# yes 同意5.第五步:测试往 7000 上写 set name jack 这个数据,写不进去原因是:name被hash后,得到的槽不归 7000管[0--5460槽]返回给我们错误,让我们去7001(具体看分配的槽决定去那个看)上写,顺利写进去6.第六步:查看机器信息cluster nodescluster info7.使用集群模式连接,自动切换到不同节点,这样就不需要在对应的槽所对应的主库写了,会自动找redis-cli -p 7000 -c8.这样之后,停掉一个主库,原来的从库会升级为主库
4.Python中操作redis集群
pip3 install redis-py-cluster 安装模块from rediscluster import RedisCluster
startup_nodes = [{"host":"127.0.0.1", "port": "7005"},{"host":"127.0.0.1", "port": "7001"},{"host":"127.0.0.1", "port": "7002"}]
rc = RedisCluster(startup_nodes=startup_nodes)
rc.set("foo", "bar")
print(rc.get("foo"))
5.集群扩容
'基于上面的6台机器(3个节点),扩成8台机器(4个节点)'1 准备两台机器sed 's/7000/7006/g' redis-7000.conf > redis-7006.confsed 's/7000/7007/g' redis-7000.conf > redis-7007.conf2 启动两台机器redis-server ./redis-7006.confredis-server ./redis-7007.conf3 两台机器加入到集群中去redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000(后面的127.0.0.1:7000到7005都可以,相当于向集群中任何一个人去说明加入即可)redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000(同上解释一样)4 让7007复制7006redis-cli -p 7007 cluster replicate 88610dbe6c3938b43e529043cb98ad9e8949b0ef'这样弄完,没有槽,就无用'5 迁移槽redis-cli --cluster reshard 127.0.0.1:7000 # 重新分配槽-迁移4096个槽 16384/4 # 因为是8个机器,四个节点,所以用16384/4 平均分配槽,也可以不均匀,我这里使用均匀-让7006的机器接收槽 7006的id号:88610dbe6c3938b43e529043cb98ad9e8949b0ef-all 从每个主库槽中迁移一个到7006,all就是让自动弄,否则就是自己来分配
6.集群缩容
'基于上面的8台机器(4个节点),缩容成6台机器(3个节点)'第一步:下线迁槽(把7006的1366个槽迁移到7000上)from 7006的0-1365的槽,在返回给之前的7000redis-cli --cluster reshard --cluster-from 88610dbe6c3938b43e529043cb98ad9e8949b0ef --cluster-to f48f088daf59ad15950e5d665be89e6389e3430d --cluster-slots 1365 127.0.0.1:7000yesfrom 7006的5461-6826的槽,在返回给之前的7001redis-cli --cluster reshard --cluster-from 88610dbe6c3938b43e529043cb98ad9e8949b0ef --cluster-to f650a325f3f7bf63265fcf9bc2dac69e3d7042be --cluster-slots 1366 127.0.0.1:7001yesfrom 7006的10923-12287的槽,在返回给之前的7002redis-cli --cluster reshard --cluster-from 88610dbe6c3938b43e529043cb98ad9e8949b0ef --cluster-to 7fd6951117dadf8f738d5d2637ed3c921bc7aa6d --cluster-slots 1365 127.0.0.1:7002yes第二步:下线节点 忘记节点,关闭节点redis-cli --cluster del-node 127.0.0.1:7000 408242644423ff0d9d29434f7c7c5450b0ec996f # 先下从,再下主,因为先下主会触发故障转移redis-cli --cluster del-node 127.0.0.1:7000 7947d7df93b5a66832068f6baed8af7d823b02c3第三步:关掉其中一个主,另一个从立马变成主顶上, 重启停止的主,发现变成了从
四、缓存更新策略
'如果内存中redis数据满了,再继续往里存数据,redis会触发缓存更新的策略'有如下几种:LRU/LFU/FIFO算法剔除:例如maxmemory-policy(到了最大内存,对应的应对策略)1.LRU -Least Recently Used,没有被使用时间最长的2.LFU -Least Frequenty User,一定时间段内使用次数最少的3.FIFO -First In First Out,最早放进去的key4.LIRS (Low Inter-reference Recency Set)是一个页替换算法,相比于LRU(Least Recently Used)和很多其他的替换算法,LIRS具有较高的性能。这是通过使用两次访问同一页之间的距离(本距离指中间被访问了多少非重复块)作为一种尺度去动态地将访问页排序,从而去做一个替换的选择
'配置文件中设置:'1.LRU配置>maxmemory-policy:volatile-lru>(1)noeviction: 如果内存使用达到了maxmemory,client还要继续写入数据,那么就直接报错给客户端>(2)allkeys-lru: 就是我们常说的LRU算法,移除掉最近最少使用的那些keys对应的数据,ps最长用的策略>(3)volatile-lru: 也是采取LRU算法,但是仅仅针对那些设置了指定存活时间(TTL)的key才会清理掉>(4)allkeys-random: 随机选择一些key来删除掉>(5)volatile-random: 随机选择一些设置了TTL的key来删除掉>(6)volatile-ttl: 移除掉部分keys,选择那些TTL时间比较短的keys2.LFU配置 Redis4.0之后为maxmemory_policy淘汰策略添加了两个LFU模式:>volatile-lfu:对有过期时间的key采用LFU淘汰算法>allkeys-lfu:对全部key采用LFU淘汰算法>还有2个配置可以调整LFU算法:>lfu-log-factor 10>lfu-decay-time 1>lfu-log-factor可以调整计数器counter的增长速度,lfu-log-factor越大,counter增长的越慢。>lfu-decay-time是一个以分钟为单位的数值,可以调整counter的减少速度
五、缓存穿透,缓存击穿,缓存雪崩
'缓存穿透'
描述:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:1 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;2 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击3 通过布隆过滤器实现:把所有用户id放到布隆过滤器中---》请求过来---》去布隆过滤器中检查 id在不在,如果在---》数据肯定有---》继续往后走 ---》如果布隆过滤器中没有---》不是我们的数据---》直接拒绝'缓存击穿'
描述:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案:设置热点数据永远不过期。'缓存雪崩'
描述:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:1 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。2 如果缓存数据库是分布式部署,将热点数据均匀分布在不同得缓存数据库中。3 设置热点(访问最多)数据永远不过期。你知道redis的跳跃表吗?-听说过,它是redis 存储有序集合底层的数据结构