Redis作为一款NoSQL内存数据库,其丰富的数据类型、简单易用的命令、单机可达10万的高并发(官方数据),从面世以来就深受广大用户的喜爱。Redis的五种数据类型,是我们学习Redis时的必修课,但是大多数人都只是去学它的命令、API,却不知道这些数据类型都能应用在哪些场景,那这些命令学起来也就会很快就忘,终究只是“纸上谈兵”。
用好这五种数据类型将给你的开发带来很大的便利,给你的程序带来很大的性能提升,同时这五种数据类型能玩出很多花样。
不过大多数同学,在实际的开发过程中,大多只用到了Redis五种数据类型中的1-3种,甚至有的只用过一种String类型。要么是业务场景简单用string足矣,要么就是根本不知道或想不到用别的数据类型更合适,那么即使是有些场景更适合用别的数据类型,可能自己也发觉不到。所以今天就来聊聊Redis的各种数据类型以及各自适用于什么场景。
Redis一共提供了5种数据类型,分别是String,Hash,List,Set,sorted set(Zset),下面就从各个数据类型的基本常用命令和使用场景分别说说吧。
String 字符串
字符串结构的常用命令
#字符串常用操作
SET key value //存入字符串键值对
MSET key value [key value ...] //批量存储字符串键值对
SETNX key value //存入一个不存在的字符串键值对
GET key //获取一个字符串键值
MGET key [key ...] //批量获取字符串键值
DEL key [key ...] //删除一个键
EXPIRE key seconds //设置一个键的过期时间(秒)
#原子加减
INCR key //将key中储存的数字值加1
DECR key //将key中储存的数字值减1
INCRBY key increment //将key所储存的值加上increment
DECRBY key decrement //将key所储存的值减去decrement
这里列出了一些String常用命令,我们看一下这些String类型的这些命令可以应用到哪些场景
应用场景
1.单值缓存
即最简单的key-value的set和get,比如缓存个标识,开关等
2.对象缓存
#1
SET user:1 value(json串)
GET user:1
#2
MSET user:1:name 编程大道 user:1:sex 1
MGET user:1:name user:1:sex
第一种直接将对象转换成json串作为value存储到redis,这种获取对象就比较简单了,直接get key拿到value转成对象即可,但有个缺点就是如果你要是修改对象的某一个字段,也得把整个对象的json串拿出来反序列化成对象,这将带来不必要的网络开销(即便是redis存在内存中,但实际我们的应用服务器和redis是隔离的,网络传输的开销也不容小觑),同样,频繁的序列化反序列化也将会带来不小的性能开销,如果对于性能要求比较高的系统来说这将是一个灾难。
而第二种存储对象的方式则对于这种频繁修改对象某一个字段的场景就比较友好了,每个字段与值都是一个kv对,修改直接set k v覆盖就好了,但是存储多个字段时就没那么容易了,好在有mset批量操作的命令,网络开销由多次变为1次。
key命名也可以根据(对象):(ID):(字段)的结构进行命名
3.分布式锁
如下setnx命令是set if not exit的缩写,意思就是这个key不存在时才执行set。多个线程执行这条命令时只有一个线程会执行成功,则视为拿到锁。然后拿到锁的线程执行业务操作,执行完毕删除这个锁,释放锁。
#setnx key value
SETNX product:10001 true //返回1代表获取锁成功
SETNX product:10001 true //返回0代表获取锁失败
//执行业务操作
DEL product:10001 //执行完业务释放锁
上述方式存在问题:程序意外终止可能会导致锁没办法释放,造成死锁。可以使用如下命令,既设置分布式锁又设置了key的过期时间
SET product:10001 true ex 10 nx //防止程序意外终止导致死锁
如上图我们可以看到ttl时间只剩5了到期就会自动释放
4.计数器
基于Redis原子自增命令incr可以实现诸如计数器的功能,我们都知道公众号文章,微博,博客都有一个阅读量的概念,我们就可以用这个计数器来实现,而且性能很高。
INCR article:readcount:{文章id}
GET article:readcount:{文章id}
5.Web集群session共享解决方案
系统集群部署情况下首先要考虑的问题就是session共享问题,我们可以通过将原本存储在内存中由tomcat管理的session转移到由Redis来存储,实现分布式session的功能。spring框架提供了session共享的解决方案,即spring session + redis实现分布式session。
6.分布式系统全局序列号
分布式系统中要保证全局序列号的唯一性,可以使用Redis来维护一个自增的序列。
通过如下命令从Redis获取自增ID:
#1
INCR orderId//INCR是一个原子自增命令
#2
INCRBY orderId 1000//redis批量生成序列号提升性能
分布式系统环境下通过Redis保证ID的自增性和唯一性,通过该命令获取ID每次都要和Redis进行交互,如果业务量很大,那么这将会很频繁。
所以可以一次性获取一定量的ID保存在JVM内存中,用完了再从Redis获取。这样减少了频繁的网络开销,但是缺点是可能会丢失(浪费)一部分ID,因为获取后服务可能挂了还没用完的ID可能就浪费了(当然你可以使用一些手段去保证不浪费,但没必要,浪费一点也是无所谓的)。
方法2,每次获取1000个