Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如
字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)
与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了
复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU
eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过
Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
1.redis的数据类型
1.1.字符串Strings
附上reids命令中文网址:
http://www.redis.cn/topics/data-types-intro.html#strings
## 设置key的值value:set key value
set name zhangsan
## 获取key的值value:get key
get name
## 当key存在时SET会失败,否则执行成功:set key value nx
set name zhangsan nx
## 当key存在时执行成功,否则执行失败:set key value xx
set age 10 xx
## 批量添加:mset key value key value ...
mset a 10 b 20 c 30
## 批量查询:mget key ...
mget a b c
##exists命令存在返回1,不存在返回0:exists key
exists name
##del命令返回1表示存在且删除,返回0表示不存在:del key
del name
##type命令返回key对应的值的存储类型:type key
type age
1.2.列表list
list元素可重复,类似于java中的数组,区别于set和zset
##lpush命令向list的左边(头部)添加一个新元素:lpush key value value ...
lpush list a b
##rpush命令向list的右边(尾部)添加一个新元素:rpush key value value ...
rpush list a
##lrange命令可以从list中取出一定范围[索引]的元素:lrange key start stop
lrange list 0 -1 ##取出list所有元素
## pop从list中删除元素并同时返回删除的值
lpop list ## 从左边开始:lpop key
rpop list ## 从右边开始:rpop key
##del命令删除list列表:del key
del list
##exists判断list是否存在:exists key
exists list
1.3.hash
##hset命令保存的值和map类似: key field value [field value ...]
hset user:1 name zhangsan age '10'
##获取user:1的name字段对应的值
hget user:1 name
##获取user:1的age字段对应的值
hget user:1 age
1.4.集合set
Set 是 redis的无序不重复集合
##SADD指令把新的元素添加到set中:sadd key member ...
sadd myset a 10
##smembers指令查看set元素:smembers key
smembers myset
##sismember查看set成员是否存在,存在返回1否则返回0:sismember key member
sismember myset a
1.5.有序集合zset
##设置zset元素:zadd key [NX|XX] [CH] [INCR] score member [score member ...]
##在score为1存放a元素
zadd zset 1 a
##在score为2存放10元素
zadd zset 2 10
##获取zset元素:zrange key start stop [WITHSCORES]
zrange zset 0 -1
##从小到大排序:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZRANGEBYSCORE zset -inf +inf ##按照score的值进行排序
##从大到小排序:ZREVRANGE key start stop [WITHSCORES]
ZREVRANGE zset 0 -1 ##按照score的值进行排序
1.6.地理位置geospatial
GEO 底层的实现原理其实就是 Zset,我们可以使用Zset命令来操作geo
##添加地理位置:geoadd key longitude latitude member [longitude latitude member ...]
##获取地理位置:geopos key member [member ...]
##获取key中两个成员的距离[米/千米/英尺/英里]:geodist key member1 member2 [m|km|ft|mi]
##以给定的经纬度为中心,找出某一半径内的元素:georadius key longitude latitude radius m|km|ft|mi
##找出位于指定元素周围的其他元素:GEORADIUSBYMEMBER key member radius m|km|ft|mi
##查看全部元素:ZRANGE key start stop
##删除元素:zrem key member [member ...]
1.7.hyperloglog
Hyperloglog 基数统计的算法,通过下面的例子可以看到效果,有点像set
区别:如果允许容错,那么使用 Hyperloglog;如果不允许容错,就使用 set
##添加元素:PFadd key element [element ...]
PFadd mykey a a 1 1 2 c 3 d e
##统计元素和:PFCOUNT key [key ...]
PFCOUNT mykey
1.8.bigmap
Bitmap 位图,该数据结构都是操作二进制位来进行记录,就只有0 和 1 两个状态
##setbit key offset value
##bitcount key [start end]
##getbit key offset
场景:张三周一到周四正常上班,周五请假
127.0.0.1:6379> setbit zhangsan 1 1
(integer) 0
127.0.0.1:6379> setbit zhangsan 2 1
(integer) 0
127.0.0.1:6379> setbit zhangsan 3 1
(integer) 0
127.0.0.1:6379> setbit zhangsan 4 1
(integer) 0
127.0.0.1:6379> setbit zhangsan 5 0
(integer) 0
查询张三这周上了几天班:
127.0.0.1:6379> bitcount zhangsan
(integer) 4
查询张三周一是否上班:
127.0.0.1:6379> getbit zhangsan 1
(integer) 1
总结: 所有的redis操作方法,都会在redis api 中找到对应的方法,所以使用Java 操作redis只需要找到其对应的方法即可。
2.redis持久化机制
redis是内存型数据库,如果不将内存里的数据保存到磁盘,那么如果服务器退出,则内存里的数据都将丢失,因此redis提供了将内存里的数据保存至磁盘的持久化机制。
2.1RDB
rdb即redis database,是redis官网默认的持久化机制,用来持久化数据,rdb文件名是dump.rdb。aof即append only file,是将redis的命令追加到文件里,当然只会保存写命令,aof文件名是dump.aof。
2.3RDB和AOF的区别
1.rdb用来保存redis数据,aof则是以追加的形式保存redis写命令,所以aof文件肯定比rdb文件大;
2.rdb通过配置文件设置持久化机制,比如如果每秒达到500写操作,那么就进行持久化操作,而aof则是记录每次对服务器写的操作,所以aof更加耗费资源;
3.由于rbd和aof持久化方式不同,所以在数据完整性方面也不同,如果服务器宕机,那么rdb肯定会丢失大量数据,aof则只会丢失最近一次写操作的数据;
4.针对数据恢复机制而言,rdb由于只是保存数据,所以恢复速度会很快;aof由于是保存的命令,所以恢复时会将所有命令一次性执行,不仅耗费资源,而且速度相对rdb慢很多。
3.reids缓存问题
3.1缓存穿透
缓存穿透指的是频繁访问一个不存在的key,从而绕过redis,直接请求底层数据库(mysql),比如恶意攻击.
解决方案:
1.在redis中设置不存在的key的值为null或者空串,进行拦截;
2.使用过滤器(布隆过滤器),在业务层逻辑进行校验,拦截不合法请求,避免数据库压力;
3.2缓存击穿
缓存击穿指的是某一个热点key突然失效,大量请求直接击穿redis落在底层数据库(mysql).
解决方案:
1.设置热点key永不失效;
2.加锁,使用分布式锁,保证对于每一个key都只有一个请求在访问;
3.3缓存雪崩
“雪崩之下没有一片雪花是无辜的”,相信大家对这句话都很熟悉,同样,redis缓存雪崩下没有哪台redis服务器是无辜的。
redis缓存雪崩是指缓存中的key大面积失效,导致请求requests直接落在底层数据库(比如mysql),直接后果就是mysql顶不住,数据库瘫痪.
原因可能是所有key同时到达失效时间,或者服务器宕机
解决方案:
1.针对缓存中的key的失效时间有计划地设置,保证不是同时失效即可;
2.服务器宕机可以考虑部署服务器集群,既可以避免高访问量导致的服务器奔溃,也可以避免断电的尴尬;
3.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的请求数量。