NoSQL
Redis-6379
什么是Redis?用处?
Redis是一个开源的高性能key-value数据库。直接从内存中读取数据,减少数据库访问压力,承受并发能力强;应用场景如下:
- 缓存(首页缓存、数据查询等)
- 消息中间件
- 计数器/排行榜
Redis和 memcached 的区别?
- Redis支持丰富的数据类型(5个);memcached仅支持简单的数据类型String
- Redis支持数据持久化,可以将内存中数据保存到磁盘中,重启后再次加载使用;memcached不支持
- Redis原生支持集群(cluster);memcached没有原生的方式
Redis 常见数据结构以及使用场景分析
String:可以是String、数字。常规计数:微博数、粉丝数
set / get / del
Hash:适合存储对象数据:购物车、商品
hset / hget / hgetall / hdel
List:内部是链表:消息列表(高性能分页,下拉不断分页)、关注列表、粉丝列表
l/rpush / lrange / l/rpop
Set:与List类似,去重。基于 set 轻易实现交集、并集、差集的操作。如共同关注、共同粉丝
sinterstore key1 key2 key3
将交集存在key1内sadd / smembers / srem
ZSet:相比Set多个score权重,按score排序。直播中礼物排行榜、在线用户列表
zadd / zrange / zrem
Redis 设置过期时间
expire /ɪkˈspaɪr/ 到期,期满;结束
set key 的时候,都可以给一个 expire time,就是过期时间。时间到后删除方式如下:
- 定期删除:redis默认是每隔 100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载!
- 惰性删除:定期删除可能会导致很多过期 key 到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉,这就是所谓的惰性删除
Redis 内存淘汰机制
但是若有的key没有被定期删除,也没有执行惰性删除。此时需要用到 Redis 内存淘汰机制
MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据?
redis 提供 6 种数据淘汰策略:
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的).
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
Redis 持久化机制
RDB(快照,snapshotting):默认方式,不需要进行配置。在一定的间隔时间中,检测key的变化情况,然后持久化数据
# after 900 sec (15 min) if at least 1 key changed save 900 1 # after 300 sec (5 min) if at least 10 keys changed save 300 10 # after 60 sec if at least 10000 keys changed save 60 10000
AOF(append-only file,只追加文件):日志记录方式,可以每一次命令操作后,持久化数据。编辑redis.windwos.conf文件
appendonly no(关闭aof) --> appendonly yes (开启aof) # appendfsync always : 每一次操作都进行持久化 appendfsync everysec : 每隔一秒进行一次持久化 # appendfsync no : 不进行持久化
缓存雪崩和缓存穿透问题解决方案
- 缓存雪崩:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
- 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
- 事中:本地 ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
- 事后:利用 redis 持久化机制保存的数据尽快恢复缓存
Redis-Cluster
Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接
分布存储机制-槽
redis-cluster 把所有的物理节点映射到[0-16383]slot(槽) 上,cluster 负责维护
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
例如三个节点:槽分布的值如下:SERVER1: 0-5460;SERVER2: 5461-10922;SERVER3: 10923-16383
容错机制-投票
选举过程是集群中所有master参与,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作,采用投票机制故障节点对应的从节点自动升级为主节点
什么时候整个集群不可用(cluster_state:fail)?
如果集群任意master挂掉,且当前master没有slave,集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态.。
Redis 为什么是单线程的
因为CPU不是Redis的瓶颈,瓶颈可能是内存或网络带宽!
异步非阻塞 IO,避免线程切换及锁的资源损耗