1、Redis简介
对于一个稍有经验的程序员,都应知道:内存条的读写速度是远高于硬盘的读写速度的,而在以往的数据库中,我们往往以硬盘为主,这样导致了读写硬盘频繁,系统效率低下,而Redis则是以内存为主,读写都尽可能的发生在内存中。
举个例子:在刚开始学习Java语言的时候,小松还没学到数据库,可是他需要保存数据,于是自己写了一个文件管理API,供自己使用。(弱化版的数据库)
后来,他发现因为只是演示作用,所以根本不需要持久化,而且又对开发效率有很大要求,于是他直接使用了HashMap做存储。(将数据存储在HashMap中,HashMap的数据放在内存中,这就是一个弱化版的Redis)。
为了方便Java程序员理解,我推荐将 Redis 理解为一个大号的HashMap。
- HashMap是键值对,Redis的数据也是以键值对的形式存储。
- HashMap不支持线程安全,Redis则是单线程应用。
- HashMap使用的是拉链法,Redis能存储List并对其操作。(强行理解)
你可以认为Redis就是C语言写出来的HashMap,并增加了远程访问,本地备份,主从复制等功能。
Redis的安装:
2、 为什么选择Redis
在简介中,我们提到了HashMap,其实在很多应用中HashMap就已经足够程序员优化数据了。
如果Redis就是一个大号的HashMap,那么为什么还需要Redis呢?
- 这里的答案应该与“为什么我们不自己实现一个文件操作系统,而使用别人写好的数据库?”相同。
- 别人写好的Redis支持了远程访问,本地备份,主从复制等等功能。
- 自己的HashMap除了操作方便(其实就是懒得学Redis,学了Jedis后会发现其实差不多方便)。没啥其他优点了。
- Redis是C语言写的,距离底层更近。(我没说C一定比Java快,Java是世界第一的语言)
- Redis花了大把大把的代码做了HashMap做不到的功能,我们为什么要重复造轮子呢?
2.1 Redis的几个特性
Redis 的持久化:
- 定期保存最新的Redis快照。
- 将所有Redis操作都保存到一个文件中。
- 以上两种都是思想,实际上做了非常多的优化,这里不展开讲。
Redis的线程安全:
- Redis是单线程应用,所以没有线程问题。
- 实际上,,Redis是有多线程的,不过绝大多数操作都是单线程,而上面的持久化就是一个多线程操作(持久化是一个只读操作)。
Redis的主从复制:
- 最开始:执行复制的从服务器会连接上主服务器,接受主服务器发送的整个数据库的初始副本;
- 之后:所有主服务执行的写命令都会发送给从服务器,让他们执行写操作。
- 很明显,主从架构可以实现读写分离,提升系统效率。
3、Redis能存储什么?
在回答这个问题之前,我先随手提下Java中最常见的几个类。
几个小问题:
Q: 为什么八大基本类型只留下了两个?
> 因为其他六个都可以用最基本的这两个表示,这两个的数据组织方式不同,所以不可以再删除。
Q: Set底层不是Map吗? 为什么还要保留?
> 因为Redis能存储Set类型,我删了还怎么讲?
接下来画出来Redis能存储的数据结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBeyOI3w-1577699124536)(C:\Users\Administrator\Pictures\Redis\Redis能存储的数据结构.png)]
Q: Redis不直接支持int和double?
对,Redis支持int和double,不过需要存入和取出时仍是String,当然你依然可以按照int来自增自减,而且其是原子操作。
4、Redis数据结构简介
先来一个没人会看的表格。
结构类型 | 结构存储的值 | 结构的读写能力 |
STRING | 能存储string,int,double | 字符串基本操作和自增自减操作 |
LIST | 类比于:LinkedList< STRING > | 支持双向队列操作,支持偏移量trimLIST 支持同时读取多个元素。 |
SET | 类比于:Set< STRING > | 支持Set的基本操作(增删改查去重) |
HASH | 类比于:HASHMAP< STRING> | 增删查单个元素,获取所有键值对。 |
ZSET | 有序集合,按照指定规则排序 | 增删查单个元素,根据规则获取相对的键值对们。 |
接下来涉及到Redis操作,请根据其他博客装上Redis后进行操作。
4.1 Redis中的字符串(STRING)
与其说是字符串,就是一个标准的HashMap<String,String>.
字符串首先是一个键值对形式,我们看看键值对的基础操作。
我们启动redis做一个演示.
127.0.0.1:6379> set hello world # 放入键值对<hello, world>
OK # 操作成功
127.0.0.1:6379> get hello # 得到键为hello的value
"world"
127.0.0.1:6379> del hello # 删除key = hello
(integer) 1 # 影响元素的个数
127.0.0.1:6379> get hello # 验证已删除
(nil) # null
上述操作很简单,也无需介绍,除这些以外,redis提供了许多对字符串的操作。不过这些内容我们等到后面专门的章节进行讲述。
4.2 Redis中的列表(LIST)
相当于HashMap<String,LinkedList< String>>.
列表相对于STRING来说,增加了许多操作,比如两端都可以进入和抛出,还可以打印下标位于(left,right)的元素。
直接上操作.
# 下面的意思是 从右侧依次放入 item,item2,item
# rpush = rightpush
127.0.0.1:6379> rpush list-key item
(integer) 1
127.0.0.1:6379> rpush list-key item2
(integer) 2
127.0.0.1:6379> rpush list-key item3
(integer) 3
# lrange 是打印下表属于 [start,stop]的所有元素。 -1为全部
127.0.0.1:6379> lrange list-key 0 -1
1) "item"
2) "item2"
3) "item3"
# get操作 lindex = 从left数的[i]个。
127.0.0.1:6379> lindex list-key 1
"item2"
# 抛出最左侧元素: lpop = leftpop;
127.0.0.1:6379> lpop list-key
"item"
# 验证是否
127.0.0.1:6379> lrange list-key 0 -1
1) "item2"
2) "item3"
127.0.0.1:6379>
4.3 Redis中的集合(SET)
相当于 HashMap<String, Set< String>>
直接上操作吧.
# set 添加操作,sadd = setAdd, 通俗易懂.
127.0.0.1:6379> sadd set-key item
(integer) 1
127.0.0.1:6379> sadd set-key item2
(integer) 1
127.0.0.1:6379> sadd set-key item3
(integer) 1
# set添加重复元素,自然会失败,所以return 0.
127.0.0.1:6379> sadd set-key item
(integer) 0
# 查看所有元素,顺序很玄学。
127.0.0.1:6379> smembers set-key
1) "item2"
2) "item3"
3) "item"
# 是否包含操作, sismember = setIsMember.询问是否是这个集合中的元素。
127.0.0.1:6379> sismember set-key item4
(integer) 0
127.0.0.1:6379> sismember set-key item
(integer) 1
# srem = set remove.删除元素.
127.0.0.1:6379> srem set-key item2
(integer) 1
127.0.0.1:6379> srem set-key item2
(integer) 0
# 查看所有元素.
127.0.0.1:6379> smembers set-key
1) "item3"
2) "item"
4.4 Redis的散列
相当于Java中的HashMap<String, HashMap<String, String>>
# hset = hash set《key,<key,value>》
127.0.0.1:6379> hset hash-key sub-key1 v1
(integer) 1
127.0.0.1:6379> hset hash-key sub-key2 v2
(integer) 1
127.0.0.1:6379> hset hash-key sub-key1 v1
(integer) 0
127.0.0.1:6379> hgetall hash-key
1) "sub-key1"
2) "v1"
# 其实,我觉得如果能打印成: "sub-key1"<--->"v1"就好了。
3) "sub-key2"
4) "v2"
# hdel = hash_delete
127.0.0.1:6379> hdel hash-key sub-key2
(integer) 1
127.0.0.1:6379> hget hash-key sub-key1
"v1"
127.0.0.1:6379> hgetall hash-key
1) "sub-key1"
2) "v1"
127.0.0.1:6379> hset hash-key sub-key1 v2
(integer) 0
127.0.0.1:6379> hgetall hash-key
1) "sub-key1"
2) "v2"
4.5 Redis的有序集合.
有序集合可以类比Java中的TreeMap,这个是字定义分数。
操作:
127.0.0.1:6379> zadd zset-key 728 m1
(integer) 1
127.0.0.1:6379> zadd zset-key 982 m0
(integer) 1
127.0.0.1:6379> zadd zset-key 982 m0
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) "m1"
2) "728"
3) "m0"
4) "982"
127.0.0.1:6379> zrangebyscore zset-key 0 800 withscores
1) "m1"
2) "728"
127.0.0.1:6379> zrem zset-key m1
(integer) 1
127.0.0.1:6379> zrem zset-key m1
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) "m0"
2) "982"
127.0.0.1:6379>