redis学习笔记

一、NoSQL

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL一般应用于超大规模数据的存储。关系型数据库已经不适合处理当今成倍数据量增加的大型互联网商务应用了。这时nosql数据库由于其更高的性能、更快的速度、更好的可扩展性等优势对解决大规模数据起到了良好的应用作用。

二、NoSQL四大分类

分类Examples举例典型应用场景数据模型优点缺点
键值(key-value)Redis,Tokyo Cabinet/Tyrant, Voldemort, Oracle BDB内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。Key 指向 Value 的键值对,通常用hash table来实现查找速度快数据无结构化,通常只被当作字符串或者二进制数据
列存储数据库Cassandra, HBase, Riak分布式的文件系统以列簇式存储,将同一列数据存在一起查找速度快,可扩展性强,更容易进行分布式扩展功能相对局限
文档型数据库CouchDB, MongoDbWeb应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容)Key-Value对应的键值对,Value为结构化数据数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构查询性能不高,而且缺乏统一的查询语法。
图形(Graph)数据库Neo4J, InfoGrid, Infinite Graph社交网络,推荐系统等。专注于构建关系图谱图结构利用图结构相关算法。比如最短路径寻址,N度关系查找等很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。

NoSQL适用场景

1、数据模型比较简单;

2、需要灵活性更强的IT系统;

3、对数据库性能要求较高;

4、不需要高度的数据一致性;

5、对于给定key,比较容易映射复杂值的环境。

NoSQL优缺点

优点缺点
数据高并发读写ACID相比于关系型数据库过于简单
海量数据存储和访问效率高无法做太复杂的关系数据库模型
对数据可扩展且高可用

三、Redis

1. 简介

Rediskey-value(键值对)的存储系统。支持存储的value类型相对更多,包括stringlistset(集合)、zset(有序集合)和hash(哈希类型)。

一般来说:

Oraclemysqlsqlserver等这样的关系型数据库主要用于存放持久化数据,将数据存储在硬盘中,读取速度较慢。而redis主要将数据存储在缓存中,缓存的读取速度快,能够大大的提高运行效率,但相应的保存时间有限。

使用Redis的情景一般是会话缓存(session cache),用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化,即可以将内存中的数据序列化到硬盘中,如此以确保用户数据的安全性。此外Redis哎集群方面具有很好的优势。

2. 安装

2.1 window下安装

步骤大致如下:

2.1.1下载

下载地址:https://github.com/microsoftarchive/redis/releases

比如下载 Redis-x64-3.0.504.zip

2.1.2 启动和关闭

解压到任意目录后,点击安装目录里的redis-server.exe即可启动,关闭redis-server.exe启动的窗口即可关闭。

2.2.3 开启后台守护进程

cmd进入安装目录并执行以下命令即可安装成系统守护进程服务。(当然你可以将安装目录放到环境变量中,就可以在任意目录执行redis命令了,这里为了简便就不做此操作了)

1
redis-server --service-install redis.windows-service.conf --loglevel verbose

(1)启动和关闭守护进程服务

1
2
3
4
#启动(如果启动失败,在安装目录里创建一个名称为Logs的文件夹即可)
redis-server --service-start
#关闭
redis-server --service-stop
2.2.4 卸载
  • 如果没有开启守护进程服务,那么直接删除安装目录即可卸载。

  • 如果开启守护进程服务,那么可在安装目录里通过执行以下命令来卸载守护进程服务,执行该命令后删除安装目录即可完全卸载。

1
redis-server --service-uninstall

更多内容可参考菜鸟教程

2.2 Linux下安装

这里主要讲linux下编译安装。

2.2.1 下载

下载地址: https://redis.io/download ,这里使用的是3.0版本。

1
2
#下载redis-3.0.0
$ wget http://download.redis.io/releases/redis-3.0.0.tar.gz
2.2.2 安装
1
2
3
4
5
#解压到/usr/local/
$ tar -zxvf redis-3.0.0.tar.gz -C /usr/local/
# 进入到解压的文件中并执行make进行编译
$ cd /usr/local/redis-3.0.0
$ make

看到类似“Hint: It's a good idea to run 'make test' ;)”这样的提示表示编译完成。make 后编译好的文件会保存到src目录下。这些文件中有两个重要的文件:

redis-server 服务端程序

redis-cli 客户端程序

其实这个时候我们已经可以执行redis-serverredis-cli 直接使用了,但为了更好的管理程序,我们可以将这些编译好的文件和配置文件移动到其他目录去。如/usr/local/redis/bin//usr/local/redis/etc/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#创建两个目录用来存放redis配置文件和编译好的文件
$ mkdir -p /usr/local/redis/bin/
$ mkdir -p /usr/local/redis/etc/

#进入编译目录
$ cd /usr/local/redis-3.0.0/src
#copy编译好的可执行文件到/usr/local/redis/bin/,注意下面从“cp /usr/..”直到“/usr/local/redis/bin/”是一条完整的命令。
$ cp /usr/local/redis-3.0.0/src/mkreleasehdr.sh \
redis-benchmark \
redis-check-aof \
redis-check-dump \
redis-cli \
redis-server \
redis-sentinel \
redis-trib.rb \
/usr/local/redis/bin/

#copy redis配置文件到/usr/local/redis/etc/
$ cp /usr/local/redis-3.0.0/redis.conf /usr/local/redis/etc/
2.2.3 卸载

直接删除/usr/local/redis-3.0.0/usr/local/redis/bin//usr/local/redis/etc/目录即可完成卸载。

3. 服务端常用命令和配置

3.1 启动服务端

1
2
#redis-server + redis配置文件 一起启动服务
$ /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

可以通过打开另一个终端执行ps -ef | grep redis 或者 ps -ef | grep 6379查看redis线程。

可以按Ctrl+C中断停止服务端启动。

3.2 配置服务端

默认开启redis-server需要保持当前终端开启才能使用,如果关闭当前终端或者中断进程了那么服务就关闭了,如果希望后台启守护进程,我们可以修改redis的配置文件,修改daemonize的值为yes来实现。

1
2
3
$ vim /usr/local/redis/etc/redis.conf
#默认daemonize为no,修改为yes表示开启守护进程
daemonize yes

注意重启redis-server后才能生效

以下是其他配置,但学习的话并不建议

1
2
3
4
5
port 6379  #默认端口,可以修改
timeout 0 #客户端空闲N秒后关闭连接

#dir ./ #日志文件和序列化文件等默认存当前目录,可进行如下进行修改到指定目录
dir /usr/local/redis/etc/

3.3 启动服务端守护进程

1
$ /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

3.4 关闭服务端守护进程

1
$ /usr/local/redis/bin/redis-cli shutdown

4. 客户端使用

4.1 启动客户端

1
$ /usr/local/redis/bin/redis-cli

4.2 关闭客户端

Ctrl+C就能停止客户端启动

5. 常用命令大全

5.1 key相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ keys *  #查询当前库的所有键  
$ EXISTS key #检查给定 key 是否存在
$ DUMP key #序列化给定key,并返回被序列化的值
$ EXPIRE key seconds #为给定 key 设置过期时间,以秒计。
$ EXPIREAT key timestamp # EXPIREAT 的作用和EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX时间戳(unix timestamp)
$ KEYS pattern #查找所有符合给定模式( pattern)的 key。
$ MOVE key db #将当前数据库的 key移动到给定的数据库 db 当中。
$ PERSIST key #移除key的过期时间,key将持久保持。
$ PTTL key #以毫秒为单位返回key的剩余的过期时间。
$ TTL key #以秒为单位,返回给定key的剩余生存时间(TTL, time to live)。
$ RANDOMKEY #从当前数据库中随机返回一个 key。
$ RENAME key newkey #修改 key的名称
$ RENAMENX key newkey # 仅当newkey不存在时,将 key改名为 newkey。
$ TYPE key #返回key所储存的值的类型。

案例

(1)查询当前库的所有键
1
2
127.0.0.1:6379> keys *
(empty list or set)
(2)修改 key的名称
1
2
3
4
127.0.0.1:6379> set name qcmoke
OK
127.0.0.1:6379> rename name username
OK

5.2 String相关

1
2
3
4
5
6
7
$ set key value  #添加键值对
$ setnx key value #如果不存在key则设置,存在则不设置
$ get key #查询对应键值
$ del key #删除对应键值
$ setex key seconds value #设置key/value的有效期,到时后变为nil(空)
$ SETRANGE KEY_NAME OFFSET VALUE #指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始
$ GETSET key value #将给定 key 的值设为 value ,并返回 key 的旧值(old value)。

案例

(1)添加键值对
  • set key value
1
2
127.0.0.1:6379> set name zhangsan
OK

如果已经存在相应的key/value,那么会将原本的值覆盖掉。添加完成后,会根据配置文件中的dir的路径每隔一段时间序列化生成dump.rdb文件。这个文件可以备份和删除,但删除了相应的数据库中就没有相应的数据了,故不要轻易的删除,这很危险。

  • setnx key value

如果不存在key则设置,如果存在key则不设置

1
2
127.0.0.1:6379> setnx name qcmoke
(integer) 1
(2)查询对应键值
  • get key
1
2
127.0.0.1:6379> get name
"zhangsan"
(3)删除已存在的键
  • del key
1
2
127.0.0.1:6379> del name
(integer) 1

5.3 哈希(Hash)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ HDEL key field1 [field2]  #删除一个或多个哈希表字段
$ HEXISTS key field #查看哈希表 key 中,指定的字段是否存在。
$ HGET key field #获取存储在哈希表中指定字段的值。
$ HGETALL key #获取在哈希表中指定 key 的所有字段和值
$ HINCRBY key field increment #为哈希表 key 中的指定字段的整数值加上增量 increment
$ HINCRBYFLOAT key field increment #为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
$ HKEYS key #获取所有哈希表中的字段
$ HLEN key #获取哈希表中字段的数量
$ HMGET key field1 [field2] #获取所有给定字段的值
$ HMSET key field1 value1 [field2 value2 ] #同时将多个 field-value (域-值)对设置到哈希表 key 中。
$ HSET key field value #将哈希表 key 中的字段 field 的值设为 value 。
$ HSETNX key field value #只有在字段 field 不存在时,设置哈希表字段的值。
$ HVALS key #获取哈希表中所有值
$ HSCAN key cursor [MATCH pattern] [COUNT count] #迭代哈希表中的键值对。

案例

(1)将哈希表 key 中的字段 field 的值设为 value
1
127.0.0.1:6379> hmset user age 21
(2)将多个 field-value (域-值)对设置到哈希表 key 中
1
127.0.0.1:6379> hmset user name zhangsan description "a good boy"
(3)从hash里获取指定字段的值
1
2
3
127.0.0.1:6379> hget user name
"zhangsan"
127.0.0.1:6379>
(4)从hash获取指定 key 的所有字段和值
1
2
3
4
5
6
7
127.0.0.1:6379> hgetall user
1) "name"
2) "zhangsan"
3) "description"
4) "a good boy"
5) "age"
6) "21"
(5)从hash获取指定 key 的所有值
1
2
3
4
127.0.0.1:6379> hvals user
1) "zhangsan"
2) "a good boy"
3) "21

5.4 列表(List)

根据收尾添加的不同,既可以实现栈,也可以实现队列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ BLPOP key1 [key2 ] timeout # 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
$ BRPOP key1 [key2 ] timeout # 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
$ BRPOPLPUSH source destination timeout # 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
$ LINDEX key index # 通过索引获取列表中的元素
$ LINSERT key BEFORE|AFTER pivot value # 在列表的元素前或者后插入元素
$ LLEN key # 获取列表长度
$ LPOP key # 移出并获取列表的第一个元素
$ LPUSH key value1 [value2] # 将一个或多个值插入到列表头部,实现先进后出的效果(栈)
$ LPUSHX key value # 将一个值插入到已存在的列表头部
$ LRANGE key start stop # 获取列表指定范围内的元素
$ LREM key count value # 移除列表元素
$ LSET key index value # 通过索引设置列表元素的值
$ LTRIM key start stop # 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
$ RPOP key # 移除列表的最后一个元素,返回值为移除的元素。
$ RPOPLPUSH source destination # 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
$ RPUSH key value1 [value2] # 在列表中末尾添加一个或多个值,实现先进先出的效果(队列)
$ RPUSHX key value # 为已存在的列表添加值

案例

(1)将一个或多个值插入到列表头部
1
2
3
4
127.0.0.1:6379> lpush lkey zhangsan
(integer) 1
127.0.0.1:6379> lpush lkey lisi wangwu
(integer) 3
(2)获取列表指定范围内的元素
1
2
3
4
127.0.0.1:6379> LRANGE lkey 0 10
1) "wangwu"
2) "lisi"
3) "zhangsan"

5.5 集合Set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ SADD key member1 [member2]    #向集合添加一个或多个成员
$ SCARD key #获取集合的成员数
$ SDIFF key1 [key2] #返回给定所有集合的差集
$ SDIFFSTORE destination key1 [key2] #返回给定所有集合的差集并存储在 destination 中
$ SINTER key1 [key2] #返回给定所有集合的交集
$ SINTERSTORE destination key1 [key2] #返回给定所有集合的交集并存储在 destination 中
$ SISMEMBER key member #判断 member 元素是否是集合 key 的成员
$ SMEMBERS key #返回集合中的所有成员
$ SMOVE source destination member #将 member 元素从 source 集合移动到 destination 集合
$ SPOP key #移除并返回集合中的一个随机元素
$ SRANDMEMBER key [count] #返回集合中一个或多个随机数
$ SREM key member1 [member2] #移除集合中一个或多个成员
$ SUNION key1 [key2] #返回所有给定集合的并集
$ SUNIONSTORE destination key1 [key2] #所有给定集合的并集存储在 destination 集合中
$ SSCAN key cursor [MATCH pattern] [COUNT count] #迭代集合中的元素

案例

(1)向集合添加一个或多个成员
1
2
3
4
5
6
127.0.0.1:6379> sadd skey zhangsan
(integer) 1
127.0.0.1:6379> sadd skey lisi
(integer) 1
127.0.0.1:6379> sadd skey wangwu zhaoliu
(integer) 1
(2)返回集合中的所有成员
1
2
3
4
5
127.0.0.1:6379> smembers skey
1) "zhaoliu"
2) "zhangsan"
3) "wangwu"
4) "lisi"

5.6 有序集合(sorted set)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ ZADD key score1 member1 [score2 member2]  #向有序集合添加一个或多个成员,或者更新已存在成员的分数
$ ZCARD key #获取有序集合的成员数
$ ZCOUNT key min max #计算在有序集合中指定区间分数的成员数
$ ZINCRBY key increment member #有序集合中对指定成员的分数加上增量 increment
$ ZINTERSTORE destination numkeys key [key ...] # 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
$ ZLEXCOUNT key min max # 在有序集合中计算指定字典区间内成员数量
$ ZRANGE key start stop [WITHSCORES] # 通过索引区间返回有序集合成指定区间内的成员
$ ZRANGEBYLEX key min max [LIMIT offset count] # 通过字典区间返回有序集合的成员
$ ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] # 通过分数返回有序集合指定区间内的成员
$ ZRANK key member # 返回有序集合中指定成员的索引
$ ZREM key member [member ...] # 移除有序集合中的一个或多个成员
$ ZREMRANGEBYLEX key min max # 移除有序集合中给定的字典区间的所有成员
$ ZREMRANGEBYRANK key start stop # 移除有序集合中给定的排名区间的所有成员
$ ZREMRANGEBYSCORE key min max # 移除有序集合中给定的分数区间的所有成员
$ ZREVRANGE key start stop [WITHSCORES] # 返回有序集中指定区间内的成员,通过索引,分数从高到底
$ ZREVRANGEBYSCORE key max min [WITHSCORES] # 返回有序集中指定分数区间内的成员,分数从高到低排序
$ ZREVRANK key member # 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
$ ZSCORE key member # 返回有序集中,成员的分数值
$ ZUNIONSTORE destination numkeys key [key ...] # 计算给定的一个或多个有序集的并集,并存储在新的 key 中
$ ZSCAN key cursor [MATCH pattern] [COUNT count] # 迭代有序集合中的元素(包括元素成员和元素分值)

案例

(1)向有序集合添加一个或多个成员,或者更新已存在成员的分数

1
2
3
4
5
6
7
127.0.0.1:6379> zadd sskey 1 zhangsan
(integer) 1
127.0.0.1:6379> zadd sskey 2 lisi
(integer) 1
127.0.0.1:6379> zadd sskey 2 wangwu
(integer) 1
127.0.0.1:6379> zadd sskey 3 zhaoliu

(2)过索引区间返回有序集合成指定区间内的成员

1
2
3
4
5
127.0.0.1:6379> zrange sskey 0 10
1) "zhangsan"
2) "lisi"
3) "wangwu"
4) "zhaoliu"

(3)取分数和值

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> zrange sskey 0 10 WITHSCORES
1) "zhangsan"
2) "1"
3) "lisi"
4) "2"
5) "wangwu"
6) "2"
7) "zhaoliu"
8) "3"

5.7 高级命令

1
2
3
4
5
6
$ select [数据库下标] #选择数据库,数据库为0--15(16个),默认进入第0个
$ move [key] [数据库下标] #将当前数据库的key移动到其他数据库
$ info #查看redis信息
$ flushdb #清空当前数据库的key
$ flushall #清空所有数据库的key
$ dbsize #查看当前数据库key的数量

案例

(1)切换到下标为某个数字的数据库
1
2
127.0.0.1:6379> select 1
OK
(2)清空当前数据库的key
1
2
3
4
5
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>

关键字可大小写

更多命令请参考:https://redis.io/commands

6. 集群

6.1 主从复制

1556744384425

主节点具有可读可写权限;而从节点只有可读操作

实验测试:

(1)网络环境

master:

ip: 10.51.220.137

port: 6379

密码:无

防火墙都已关闭

slave0:

ip: 10.51.220.136

port: 6379

密码:无

防火墙都已关闭

(2)操作步骤

主节点

1
2
3
4
5
6
7
8
#启动服务器
$ /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

#启动客户端
[root@localhost ~]# /usr/local/redis/bin/redis-cli

#设置测试数据
127.0.0.1:6379> set name master

从节点:

slave0根据主节点master的ip、端口、密码(如果主节点没有设置密码那么slave不配置)修改配置文件。

1
2
3
4
5
6
7
8
#修改配置文件,配置master的ip、端口、密码(如果主节点没有设置密码那么slave不配置)。
$ vim /usr/local/redis/etc/redis.conf
#配置master的ip、端口
#slaveof <masterip> <masterport> #默认注释,是主节点,不配置主节点的话,默认当前节点就是master主节点
slaveof 10.51.220.137 6379

#设置master的密码
# masterauth <master-password>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#启动服务器
$ /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

#启动客户端
[root@localhost ~]# /usr/local/redis/bin/redis-cli

#查看所有key,发现自动根据master的数据进行了更新
127.0.0.1:6379> keys *
1) "name"

#查看数据库信息
127.0.0.1:6379> info
...
...
# Replication
role:slave #当前节点的角色是从节点
master_host:10.51.220.137 #主节点ip
master_port:6379 #主节点port
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:855
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
...
...

主节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#查看数据库信息
127.0.0.1:6379> info
...
...
# Replication
role:master #当前节点的角色是主节点
connected_slaves:1 #当前从节点的个数为1
slave0:ip=10.51.220.136,port=6379,state=online,offset=1079,lag=1 #从节点的信息
master_repl_offset:1079
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1078
...
...


----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%