### Redis
#### Redis常见数据结构以及使用场景分析
##### String
> 常用命令:set,get,decr,incr,mget等
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。常规key-value缓存应用;常规计数:微博数,粉丝数等。
##### Hash
> 常用命令:hget,hset,hgetall等
hash是一个String类型的field和value的映射表,hash特别适合用于存储对象,后续操作的时候。
##### List
> 常用命令:lpush,rpush,lpop,rpop,lrange
list 就是链表,Redis list 的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的 list 结构来实现。
Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
另外可以通过 lrange 命令,就是从某个元素开始读取多少个元素,可以基于 list 实现分页查询,这个很棒的一个功能,基于 redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西(一页一页的往下走),性能高。
##### Set
> 常用命令: sadd,spop,smembers,sunion 等
set 对外提供的功能与list类似是一个列表的功能,特殊之处在于 set 是可以自动排重的。
当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。
比如:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。
##### ZSet
> 常用命令:zadd,zrange,zrem,zcard等
和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。
#### 为什么要用redis或者为什么要用缓存
主要从“高性能”和“高并发”两点来看待这个问题。
##### 高性能
假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
##### 高并发
直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。
#### 缓存雪崩和缓存穿透问题解决方案
##### 缓存雪崩
简介:缓存同一时间大面积的失效,所以后面的请求都会落在数据库上,造成数据库短时间内承受大量请求而崩掉。
解决办法:
事前:尽量保证整个redis集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
事中:本地ehcache缓存+hystrix限流&降级,避免MySQL崩掉
事后:利用redis持久化机制保存的数据库尽快恢复缓存
##### 缓存穿透
简介:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量的请求而崩掉。
解决办法:常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
如果查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍把这个空结果进行缓存,但它的过期时间会很短,最长不超过5分钟。