Redis—基础
一、Redis介绍
1、什么是NoSQL
NoSQL,泛指非关系型的数据库,NoSQL即Not-Only SQL,它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。
NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
2、Redis发展历史
2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG,然而没过多久该公司的创始人 Salvatore Sanfilippo便 对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身定做一个数据库,并于2009年开发完成,这个数据库就是Redis。 不过Salvatore Sanfilippo并不满足只将Redis用于LLOOGG这一款产品,而是希望更多的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要的代码贡献者Pieter Noordhuis一起继续着Redis的开发,直到今天。
Salvatore Sanfilippo自己也没有想到,短短的几年时间,Redis就拥有了庞大的用户群体。Hacker News在2012年发布了一份数据库的使用情况调查,结果显示有近12%的公司在使用Redis。国内如新浪微博、街旁网、知乎网,国外如GitHub、Stack Overflow、Flickr等都是Redis的用户。
VMware公司从2010年开始赞助Redis的开发, Salvatore Sanfilippo和Pieter Noordhuis也分别在3月和5月加入VMware,全职开发Redis。
3、什么是Redis
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如
下:
字符串类型(string)
散列类型(hash)
列表类型(list)
集合类型(set)
有序集合类型。(sortset)
二、安装运行Redis
1、运行环境
redis是C语言开发,建议在linux上运行,本教程使用Centos7.0作为安装环境。
安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc:yum install gcc-c++
2、安装
从官网下载:http://www.redis.cn/download.html
$ tar xzf redis-5.0.8.tar.gz $ cd redis-5.0.8 $ make
# 安装到指定目录,如 /usr/local/redis
cd /usr/local/redis-5.0.8
make PREFIX=/usr/local/redis install

cd utils 进入,会发现 redis_init_script 脚本文件,将它复制到 /etc/init.d 目录下
cp redis_init_script /etc/init.d/
1、redis.conf
redis.conf是redis的配置文件,redis.conf在redis源码目录。
注意修改port作为redis进程的端口,port默认6379。
2、拷贝配置文件到安装目录下
进入源码目录,里面有一份配置文件 redis.conf,然后将其拷贝到安装路径下
cd /usr/local/redis
cp /usr/local/tools/redis-5.0.8/redis.conf /usr/local/redis
3、安装目录下bin文件夹


4、配置 redis.conf
1、配置 bind

2、配置后端启动

3、配置工作目录

5、修改 redis_init_script 脚本

vim redis_init_script
# # Simple Redis init.d script conceived to work on Linux systems # as it does use of the /proc filesystem. ### BEGIN INIT INFO # Provides: redis_6379 # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Redis data structure server # Description: Redis data structure server. See https://redis.io ### END INIT INFO # 端口号 REDISPORT=6379
# 运行脚本路径,修改为安装 redis 目录 EXEC=/usr/local/redis/bin/redis-server CLIEXEC=/usr/local/redis/bin/redis-cli # pid redis.conf 中也可以更改,这里可以不管 PIDFILE=/var/run/redis_${REDISPORT}.pid
# redis.conf 路径 CONF="/usr/local/redis/redis.conf"
为 redis_init_script 添加权限
chmod 777 redis_init_script
3、Redis启动
1、启动
./etc/inin.d/redis_init_script start

开机启动设置:
vim redis_init_script

#chkconfig: 22345 10 90
#description: Start and Stop redis

相当于注册脚本
chkconfig redis_init_script on
4、Redis停止
./etc/init.d/redis_init_script stop
如果redis 设置了密码,那么脚本里面就要加上:-a 密码

5、Redis客户端
在redis的安装目录中有redis的客户端,即redis-cli(Redis Command Line Interface),它是Redis自带的基于命令行的Redis客户端。
1、连接Redis服务端
指定连接redis服务的ip和端口:

2、向Redis服务端发送命令
redis-cli连上redis服务后,可以在命令行发送命令。
1、ping
Redis提供了PING命令来测试客户端与Redis的连接是否正常,如果连接正常会收到回复PONG

2、set/get
使用set和get可以向redis设置数据、获取数据。

6、Redis多数据库
1、Redis实例
一个redis进程就是一个redis实例,一台服务器可以同时有多个redis实例,不同的redis实例提供不同的服务端口对外提供服务,每个redis实例之间互相影响。每个redis实例都包括自己的数据库,数据库中可以存储自己的数据。
2、对数据库测试
一个Redis实例可以包括多个数据库,客户端可以指定连接某个redis实例的哪个数据库,就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库。
一个redis实例最多可提供16个数据库,下标从0到15,客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库,如下连接1号库:

在1号库中查询上节设置的数据,结果查询不到:

重新选择第0号数据库,查询数据:

如果选择一个不存在数据库则会报错:

注意:redis不支持修改数据库的名称,只能通过select 0、select 1...选择数据库。
四、数据类型
1、string 介绍
redis中没有使用C语言的字符串表示,而是自定义一个数据结构叫SDS(simple dynamic string)即简单动态字符串。
打开下载的redis源码包,找到src下的sds.h文件查看sds源码:
struct sdshdr { //字符串长度 unsigned int len; //buf数组中未使用的字节数量 unsigned int free; //用于保存字符串 char buf[]; };
c语言对字符串的存储是使用字符数组,遇到'\0'字符则认为字符串结束,redis的字符串可以存储任何类型的数据,因为任何类型数据都可以表示成二进制,sds结构中的char buf[]就是存储了二进制数据。
redis的字符串是二进制安全的,什么是二进制安全?简单理解就是存入什么数据取出的还是什么数据。redis中的sds不像c语言处理字符串那样遇到'\0'字符则认证字符串结束,它不会对存储进去的二进制数据进行处理,存入什么数据取
1、赋值与取值
SET key value
GET key
127.0.0.1:6379> set test 123
OK
127.0.0.1:6379> get test
"123"
# 当键不存在时返回空结果。
2、向尾部追加值
APPEND key value
APPEND的作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value,即相当于 SET key value。返回值是追加后字符串的总长度。
127.0.0.1:6379> set str hello OK 127.0.0.1:6379> append str " world!" (integer) 12 127.0.0.1:6379> get str "hello world!"
3、获取字符串长度
STRLEN key
STRLEN命令返回键值的长度,如果键不存在则返回0。
127.0.0.1:6379> strlen str (integer) 0 127.0.0.1:6379> set str hello OK 127.0.0.1:6379> strlen str (integer) 5
4、同时设置/获取多个键值
MSET key value [key value …] MGET key [key …] 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> mget k1 k3 1) "v1" 2) "v3"
2、Hash
hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。如下:

1、命令
HSET key field value 一次只能设置一个字段值 HGET key field 一次只能获取一个字段值 HMSET key field value [field value ...] 一次可以设置多个字段值 HMGET key field [field ...] 一次可以获取多个字段值 HGETALL key 127.0.0.1:6379> hset user username zhangsan (integer) 1 127.0.0.1:6379> hget user username "zhangsan“ HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0. 127.0.0.1:6379> hmset user age 20 username lisi OK 127.0.0.1:6379> hmget user age username 1) "20" 2) "lisi" 127.0.0.1:6379> hgetall user 1) "age" 2) "20" 3) "username" 4) "lisi"
2、判断字段是否存在
HEXISTS key field 127.0.0.1:6379> hexists user age 查看user中是否有age字段 (integer) 1 127.0.0.1:6379> hexists user name 查看user中是否有name字段 (integer) 0 HSETNX key field value 当字段不存在时赋值,类似HSET,区别在于如果字段已经存在,该命令不执行任何操作。 127.0.0.1:6379> hsetnx user age 30 如果user中没有age字段则设置age值为30,否则不做任何操作 (integer) 0
3、其它命令
1、删除字段 可以删除一个或多个字段,返回值是被删除的字段个数
HDEL key field [field ...] 127.0.0.1:6379> hdel user age (integer) 1 127.0.0.1:6379> hdel user age name (integer) 0 127.0.0.1:6379> hdel user age username (integer) 1
2、只获取字段名或字段值
HKEYS key HVALS key 127.0.0.1:6379> hmset user age 20 name lisi OK 127.0.0.1:6379> hkeys user 1) "age" 2) "name" 127.0.0.1:6379> hvals user 1) "20"
3、List
1、介绍
列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。
列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的。
2、命令
1、 向列表两端增加元素。
LPUSH key value [value ...] RPUSH key value [value ...] 向列表左边增加元素 127.0.0.1:6379> lpush list:1 1 2 3 (integer) 3 向列表右边增加元素 127.0.0.1:6379> rpush list:1 4 5 6 (integer) 3
2、 从列表两端弹出元素
LPOP key
RPOP key
LPOP命令从列表左边弹出一个元素,会分两步完成,第一步是将列表左边的元素从列表中移除,第二步是返回被移除的元素值。
127.0.0.1:6379> lpop list:1
"3“
127.0.0.1:6379> rpop list:1
"6“
3、 获取列表中元素的个数
LLEN key 127.0.0.1:6379> llen list:1 (integer) 2
4、获取列表片段
LRANGE key start stop LRANGE命令是列表类型最常用的命令之一,获取列表中的某一片段,将返回start、stop之间的所有元素(包含两端的元素),索引从0开始。索引可以是负数,如:“-1”代表最后边的一个元素。 127.0.0.1:6379> lrange list:1 0 2 1) "2" 2) "1" 3) "4"
5、 其它命令
1、删除列表中指定的值
LREM key count value LREM命令会删除列表中前count个值为value的元素,返回实际删除的元素个数。根据count值的不同,该命令的执行方式会有所不同: 当count>0时, LREM会从列表左边开始删除。 当count<0时, LREM会从列表后边开始删除。 当count=0时, LREM删除所有值为value的元素。
2、 获得/设置指定索引的元素值
LINDEX key index LSET key index value 127.0.0.1:6379> lindex l:list 2 "1" 127.0.0.1:6379> lset l:list 2 2 OK 127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "2" 4) "2"
3、只保留列表指定片段,指定范围和LRANGE一致
LTRIM key start stop 127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "0" 4) "2" 127.0.0.1:6379> ltrim l:list 0 2 OK 127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "0"
4、 向列表中插入元素
LINSERT key BEFORE|AFTER pivot value 该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。 127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "2" 3) "1" 127.0.0.1:6379> linsert list after 3 4 (integer) 4 127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "4" 3) "2" 4) "1"
5、 将元素从一个列表转移到另一个列表中
RPOPLPUSH source destination 127.0.0.1:6379> rpoplpush list newlist "1" 127.0.0.1:6379> lrange newlist 0 -1 1) "1" 127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "4" 3) "2"
4、Set
1、介绍
在集合中的每个元素都是不同的,且没有顺序
集合类型和列表类型的对比:

集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型的Redis内部是使用值为空的散列表实现,所有这些操作的时间复杂度都为0(1)。
Redis还提供了多个集合之间的交集、并集、差集的运算。
2、命令
1、增加/删除元素
SADD key member [member ...] SREM key member [member ...] 127.0.0.1:6379> sadd set a b c (integer) 3 127.0.0.1:6379> sadd set a (integer) 0 127.0.0.1:6379> srem set c d (integer) 1
2、 获得集合中的所有元素
SMEMBERS key 127.0.0.1:6379> smembers set 1) "b" 2) "a” 判断元素是否在集合中,无论集合中有多少元素都可以极速的返回结果。 SISMEMBER key member 127.0.0.1:6379> sismember set a (integer) 1 127.0.0.1:6379> sismember set h (integer) 0
5、sorted Set
1、介绍
在集合类型的基础上有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关的操作。
在某些方面有序集合和列表类型有些相似。
1、二者都是有序的。
2、二者都可以获得某一范围的元素。
但是,二者有着很大区别:
1、列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会变慢。
2、有序集合类型使用散列表实现,所有即使读取位于中间部分的数据也很快。
3、列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
4、有序集合要比列表类型更耗内存。
2、命令
1、增加元素
向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
ZADD key score member [score member ...] 127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu (integer) 3 127.0.0.1:6379> zadd scoreboard 97 lisi (integer) 0 获取元素的分数 ZSCORE key member 127.0.0.1:6379> zscore scoreboard lisi "97"
2、 获得排名在某个范围的元素列表
获得排名在某个范围的元素列表 ZRANGE key start stop [WITHSCORES] 照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素) 127.0.0.1:6379> zrange scoreboard 0 2 1) "zhangsan" 2) "wangwu" 3) "lisi“ ZREVRANGE key start stop [WITHSCORES] 照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素) 127.0.0.1:6379> zrevrange scoreboard 0 2 1) " lisi " 2) "wangwu" 3) " zhangsan “ 如果需要获得元素的分数的可以在命令尾部加上WITHSCORES参数 127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES 1) "zhangsan" 2) "80" 3) "wangwu" 4) "94"
3、 获得指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES 1) "wangwu" 2) "94" 3) "lisi" 4) "97" 127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 (97 WITHSCORES 1) "wangwu" 2) "94“ 127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2 1) "wangwu" 2) "lisi"
4、增加某个元素的分数,返回值是更改后的分数。
ZINCRBY key increment member 给lisi加4分 127.0.0.1:6379> ZINCRBY scoreboard 4 lisi "101“ 获得集合中元素的数量 ZCARD key 127.0.0.1:6379> ZCARD scoreboard (integer) 3 获得指定分数范围内的元素个数 ZCOUNT key min max 127.0.0.1:6379> ZCOUNT scoreboard 80 90 (integer) 1
5、其他命令
1、按照排名范围删除元素
ZREMRANGEBYRANK key start stop 127.0.0.1:6379> ZREMRANGEBYRANK scoreboard 0 1 (integer) 2 127.0.0.1:6379> ZRANGE scoreboard 0 -1 1) "lisi" ZREMRANGEBYSCORE key min max 按照分数范围删除元素 127.0.0.1:6379> zadd scoreboard 84 zhangsan (integer) 1 127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100 (integer) 1
2、获取元素的排名
ZRANK key member ZREVRANK key member 从小到大 127.0.0.1:6379> ZRANK scoreboard lisi (integer) 0 从大到小 127.0.0.1:6379> ZREVRANK scoreboard zhangsan (integer) 1
6、服务器命令
1、ping
测试连接是否存活 redis 127.0.0.1:6379> ping PONG //执行下面命令之前,我们停止redis 服务器 redis 127.0.0.1:6379> ping Could not connect to Redis at 127.0.0.1:6379: Connection refused //执行下面命令之前,我们启动redis 服务器 not connected> ping PONG redis 127.0.0.1:6379> 第一个ping 时,说明此连接正常 第二个ping 之前,我们将redis 服务器停止,那么ping 是失败的 第三个ping 之前,我们将redis 服务器启动,那么ping 是成功的
2、echo
在命令行打印一些内容 redis 127.0.0.1:6379> echo HongWan "HongWan" redis 127.0.0.1:6379>
3、select
选择数据库。Redis 数据库编号从0~15,我们可以选择任意一个数据库来进行数据的存取。 redis 127.0.0.1:6379> select 1 OK redis 127.0.0.1:6379[1]> select 16 (error) ERR invalid DB index redis 127.0.0.1:6379[16]> 当选择16 时,报错,说明没有编号为16 的这个数据库
4、quit
退出连接。
redis 127.0.0.1:6379> quit
5、dbsize
返回当前数据库中key 的数目。 redis 127.0.0.1:6379> dbsize (integer) 18 redis 127.0.0.1:6379> 结果说明此库中有18 个key
6、info
获取服务器的信息和统计。 redis 127.0.0.1:6379> info redis_version:2.2.12 redis_git_sha1:00000000 redis_git_dirty:0 arch_bits:32 multiplexing_api:epoll process_id:28480 uptime_in_seconds:2515 uptime_in_days:0
7、flushdb
删除当前选择数据库中的所有key。 redis 127.0.0.1:6379> dbsize (integer) 18 redis 127.0.0.1:6379> flushdb OK redis 127.0.0.1:6379> dbsize (integer) 0 redis 127.0.0.1:6379> 在本例中我们将0 号数据库中的key 都清除了。
8、flushall
删除所有数据库中的所有key。 redis 127.0.0.1:6379[1]> dbsize (integer) 1 redis 127.0.0.1:6379[1]> select 0 OK redis 127.0.0.1:6379> flushall OK redis 127.0.0.1:6379> select 1 OK redis 127.0.0.1:6379[1]> dbsize (integer) 0 redis 127.0.0.1:6379[1]> 在本例中我们先查看了一个1 号数据库中有一个key,然后我切换到0 号库执行flushall 命令,结果1 号库中的key 也被清除了,说是此命令工作正常。


浙公网安备 33010602011771号