Redis原理与应用(1)——基本介绍
系列文章目录
Redis原理与应用(1)——基本介绍
Redis原理与应用(2)——Redis的Java客户端(码字中。。。)
前言
Redis是一种内存数据库,以key-value形式进行存储,是当前最常用的中间件之一。本文以个人的Java开发经历为基础,对Redis进行总结,以供参考和交流。如果希望系统和深入理解Redis,推荐《Redis深度历险:核心原理与应用实践》,此外Redis中文官网(http://www.redis.cn/)上也有许多资料。
一、Redis是什么?
Redis全称Remote Dictionary Server,即远程字典服务,它是一个开源的使用C语言编写的数据库。Redis是一个key-value数据库,是非关系型数据库的一种。同时它还是一个内存数据库,即其数据是存储在内存中的,当然其数据可以持久化到硬盘。上述特点使Redis拥有快速和灵活的特性,也被各大公司广泛应用,应用场景包括缓存、消息队列、计数器等。
二、安装Redis
Redis的中文官网官网上可以下载到Linux安装包和Docker镜像,当然也可以去Github上编译源码。而对于Windows环境,Github上有安装包,不过版本停留在Redis3。此处不详细说明安装方法了,自行百度。当你安装了Redis之后就可以搭建Redis服务了,同时你也可以使用客户端模式通过命令行连接和操作Redis。
直接使用命令行操作Redis不能直观的展示Redis,因此我简单的介绍一下Redis的可视化客户端。个人使用过Redis Desktop Manager和Redis Plus两种,Redis Desktop Manager在0.9.3之后就开始收费了,最经典的版本是0.8.8,它简单易用,可以使用命令行,但是缺少可视化的资源监控,0.8.8上我没有找到集群选项,应该是无法连接Redis集群的。Redis Plus是国内的团队开发的开源客户端,它的界面更美观,支持集群,但是无法使用命令行。Redis Desktop Manager开始收费后许多人转向了免费的Another Redis Desktop Manager,有兴趣可以尝试。后面我主要使用RedisDesktopManager客户端进行示例。
三、数据结构与基本操作
Redis是一个key-value数据库,它本身就是一个大的hash表,在结构上与Java的HashMap也基本一致。Redis的key是string类型,其value有五种类型:string、list、hash、set、zset。下面将解析这五种结构,同时展示它们的一些基本命令,若要获取更多的命令可以到Redis中文官网上查询。
1.string
字符串string是最基本的value类型,Redis的key也是该类型。Redis虽然是C语言编写的,但是并没有直接用C语言的字符串,而是重新设计了一种二进制安全的string结构。所谓二进制安全是指字符串不依赖某种特殊的字符,这意味着它存储任何二进制序列。也就是说我们可以将任何对象转换成二进制序列,然后将其作为Key或者Value,无论这个对象是一个简单的字符串,还是一幅图像,甚至是一个Java对象。
这里扩展一下字符串的二进制安全。C语言的string是用一个以特殊字符“\0”结尾的字符数组来表示的,根据当前字符是否为“\0”来判断字符串是否结束,liru 字符串“abc\0dfe”会被识别成“abc”,因此其不能表示全部二进制序列。而Redis的string直接存储了字符串的长度,因此没有结束判断符,是二进制安全的。
下面展示一些string的基本操作
- set命令,新增key-value,如果key已经存在,则会将原有的value覆盖;
- get命令,根据key获取value值,如果没有key,会返回空;
- exists命令,判断key是否存在,命令返回“1”代表存在,返回“0”代表不存在;
- del命令,删除key,返回值表示删除成功的key的个数,注意del命令可以批量操作多个key,若无此key则直接略;
- get和set命令如果要批量操作,需要换成对应的mget和mset。
此外还有一些其他命令,例如append命令追加字符;setnx命令当key不存在时才创建key-value,即不会覆盖原key的value;set命令后可以加上EX\PX选项,NX\XX选项;incr命令将字符串值解析成整型,将其加一。更多命令请到http://www.redis.cn上查询。
2. list
Redis的列表list是一种双向链表,它与Java的LinkedList结构基本一致,但是与ArrayList相差很大,ArrayList的本质是数组。双向链表的特性决定了它在操作表头和表尾时效率很高,但是根据索引操作时效率很低。链表和数组的优劣应该是数据结构的基础了,此处不赘述。
下面展示一下list的基本命令:
- lpush命令是向表头添加元素,lpop是删除表头元素并返回,而rpush和rpop则是对尾部元素进行相应的操作(Redis用左边代表头部,右边代表尾部,lrange、llen、lrem等命令的l不是指left,应该是指list。);
- 使用del命令直接删除整个list;
- lindex命令,获取指定索引处的元素;
- linsert命令,在指定的value值前/后插入元素;
- lrange命令,取出指定范围内的元素,偏移量也可以是负数,表示偏移量是从list尾部开始计数;
- llen命令,返回list的长度;
- lrem命令,删除头部或尾部的一些元素;
- ltrim命令,截取两个索引之间的列表,即删除索引之外的元素。
3. hash
Redis的hash结构与java的HashMap基本一致,是无序字典,存储方式是数组+链表,即由子key的hash值确定其在数组中的位置,对hash值相同的两个子key(hash碰撞)采用链表相连。
下面展示一些hash的基本命令
- hset命令,向hash中添加一个键值对,它有三个参数,第一个是整个hash在redis中的key,第二个是子key,即hash中键值对的key,第三个才是值;
- hget命令,获取hash中的值,同样只能获取hash中的一个值;
- hmget和hmset可以添加和获取hash中的多个键值对;
- hgetall命令,获取hash内所有的键值对;
- hkeys和hvals命令可以获取hash内所有的key和value;
- hdel命令,删除hash中的一个键值对,使用del命令直接删除整个hash;
- hlen命令,返回hash内键值对的数量;
- hexists命令,判断hash内是否存在某个key。
4. set
Redis的集合set与java中的HashSet基本一致,内部元素是无序的且不能重复,它可以看作是一个value都为空的hash。
下面展示set的一些基本操作
- sadd命令,向set中添加一个元素;
- srem命令,从set中删除一个元素,使用del命令删除整个set;
- scard命令,返回set中元素数量;
- smembers命令,返回set中全部元素;
- sismember命令,判断set中是否含有该元素。
5. zset
Redis的有序集合zset是一个非常有特色的结构,它和set一样内部元素不能重复,但它是有序的。那么zset是按照什么来排序的呢,zset的每一个元素都会绑定一个浮点类型的score,score在元素加入集合时就必须设定,zset根据score对元素进行排序,我们可以对指定score范围内的元素进行操作。zset的形式与java的TreeMap有些类似,TreeMap的key对应zset的score,但是TreeMap的value是可以重复的。此外TreeMap是基于红黑树实现的,而zset是基于跳表(skip list)实现的。跳表的本质是一个可以二分查找的链表,这种数据结构使zset可以快读的查询和增删,有关跳表的详细解释可以参考这篇文章https://zhuanlan.zhihu.com/p/68516038。
下面展示zset的一些基本操作
- zadd命令,向zset中添加一个元素;
- zrem命令,从zset中删除一个元素,使用del命令删除整个zset;
- zcard命令,返回zset中元素数量;
- zscore命令,返回指定元素的score,若无该元素则返回空;
- zrank命令,返回指定元素的排名,按照score升序计算,排名从0开始,zrevrank为降序;
- zrange命令,获取指定排名范围内的元素;
- zrangebyscore,获取指定score范围内的元素,参数中“(”代表不可取等于;
- zcount,返回指定score范围内的元素个数。
6.其他操作
- rename命令,重命名key;
- expire命令,设置过期时间,即在设定时间后自动删除该key;
- keys命令,遍历全部key,返回符合模式的全部key,注意当key的数量巨大时,该命令执行速度很慢,会阻塞线程,因此不建议在生产环境中使用;
- scan命令,和keys类似用来遍历符合要求的key,但它是通过游标进行的增量式遍历,不会阻塞线程,也可以限制返回数量。相应的其代价是返回的元素可能重复,也可能已经被修改。该命令较为复杂,此处不展开;
- 容器的通用规则。list、hash、set、zset都属于容器,容器内的元素都是string,容器有两个通用规则,其一是容器不存在就创建一个再执行相应的操作,其二是容器内没有元素则删除容器,回收内存;
- 对于set和zset两个集合容器,Redis还提供了交集并集等相关集合操作;
- bgsave和save命令,将内存中的数据存储到磁盘上,即Redis的持久化,此处不展开,
- Redis还有info、config、client等相关命令对服务端和客户端进行配置和状态查询。
总结
理解Redis的这五种数据结构是使用Redis的基础,但是直接使用命令行或者可视化客户端操作这些数据其实是比较少的,更多的时候我们会使用Java客户端来操作数据,这部分内容将在下一篇文章中呈现。后面可能会持续更新一些Redis的应用、原理以及优化。本文地址:https://blog.csdn.net/wegoingdown/article/details/112801098