1.什么是Redis
Redis 是一个开源的使用C语言编写,支持网络,可基于内存可持久化的日志型、高性能的Key-Value数据库,并支持多语言的API调用。它通常被成为数据结构服务器,因为Value值可以是多种数据类型(字符串(String)、集合(set)、列表(list)、哈希(Map)、有序集合(sorted set))等类型。
Redis的特点:
- Redis支持数据持久化存储,可以将内存保存的数据持久化的存放到磁盘中,重启的时候可以在次的加载使用。
- Redis不仅仅支持Key-Value类型的数据,还支持 字符串(String)、集合(set)、列表(list)、哈希(Map)、有序集合(sorted set)等多种数据类型。
- Redis支持主从模式,即master-slave模式的主从模型。
Redis的优点:
- 性能极高 (Redis能读的速度是110000次/s,写的速度是81000次/s)。
- 支持丰富的数据类型 (Redis支持二进制案例的字符串(String)、集合(set)、列表(list)、哈希(Map)、有序集合(sorted set)等多种数据类型)。
- 可用于缓存、消息、按key设置过期时间,过期自动删除。
- 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。
- 支持分布式读写分离模式。
2.安装Redis(Linux)
2.1 下载Redis:
下载Redis安装包(下载地址:http://download.redis.io/releases/)
wget http://download.redis.io/releases/redis-4.0.8.tar.gz
2.2 安装Redis:
解压、编译(编译的时候需要gcc的依赖 在安装之前一定保证gcc是安装好的,可以使用yum -y install gcc 安装)
[root@BrianZhu ~]# tar zxf redis-4.0.8.tar.gz [root@BrianZhu ~]# cd redis-4.0.8/ [root@BrianZhu redis-4.0.8]# make
2.3 启动Redis:
二进制文件是编译完成后在src目录下,通过下面的命令启动Redis服务:
[root@BrianZhu redis-4.0.8]# src/redis-server
看到下面的图片表示启动成功:
这里的启动方式,是让Redis在前台启动,我们不退出Redis终端就会一直这样显示,当我们关掉终端Redis的进程也就退出了,为了解决这个问题 我们要把Redis放到后台启动,使用下面的方法:
[root@BrianZhu redis-4.0.8]# nohup src/redis-server &
检查Redis启动状态:
[root@BrianZhu redis-4.0.8]# netstat -lntup | grep redis tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 47592/src/redis-ser tcp6 0 0 :::6379 :::* LISTEN 47592/src/redis-ser
注:redis-server默认启动的端口是6379端口,默认没有密码
在启动的时候Redis调用的是配置文件redis.conf文件(文件路径在解压后redis目录下面)
[root@BrianZhu redis-4.0.8]# pwd /root/redis-4.0.8 [root@BrianZhu redis-4.0.8]# ll | grep redis.conf -rw-rw-r-- 1 root root 58353 Feb 3 00:39 redis.conf
如果我们自定义的这个文件的路径,也可以指定这个文件的路径进行启动:
[root@BrianZhu redis-4.0.8]# nohup src/redis-server ~/redis-4.0.8/redis.conf &
2.4 启动Redis客户端并且验证:
我们可以使用内置的客户端命令redis-cli进行使用:
[root@BrianZhu redis-4.0.8]# src/redis-cli 127.0.0.1:6379> # 已经启动Redis客户端
验证(一个简单的使用):
[root@BrianZhu redis-4.0.8]# src/redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> set var "Hello World" OK 127.0.0.1:6379> get var "Hello World" 127.0.0.1:6379>
退出客户端终端:
[root@BrianZhu redis-4.0.8]# src/redis-cli 127.0.0.1:6379> quit [root@BrianZhu redis-4.0.8]# src/redis-cli 127.0.0.1:6379> exit
2.5 停止Redis:
我们可以使用内置的语法命令 redis-cli shutdown 来关闭Redis:
[root@BrianZhu redis-4.0.8]# src/redis-cli shutdown
具体操作如下:
[root@BrianZhu redis-4.0.8]# netstat -lntup | grep redis tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 47592/src/redis-ser tcp6 0 0 :::6379 :::* LISTEN 47592/src/redis-ser [root@BrianZhu redis-4.0.8]# src/redis-cli shutdown [1]+ Done nohup src/redis-server [root@BrianZhu redis-4.0.8]# netstat -lntup | grep redis [root@BrianZhu redis-4.0.8]#
注:如果是设置上密码后,单纯的使用redis-cli是关不掉的,必须加上IP、Port、Passwd
[root@BrianZhu redis-4.0.8]# src/redis-cli -h 192.168.31.1 -p 6379 -a 123456 shutdown
3.设置密码,远程连接
3.1设置Redis密码:
redis没有实现访问控制这个功能,但是它提供了一个轻量级的认证方式,可以编辑redis.conf配置来启用认证。
有两种设置密码的方式:
- 修改配置文件,需要重启redis:在配置文件中有个参数: requirepass 这个就是配置redis访问密码的参数(500行左右);比如 requirepass test123 ; 注:( redis的查询速度是非常快的,外部用户一秒内可以尝试多大150K个密码;所以密码要尽量长(对于DBA 没有必要必须记住密码)
- 使用内置的语法命令设置密码,不重启Redis设置密码:
[root@BrianZhu redis-4.0.8]# src/redis-cli 设置密码 127.0.0.1:6379> config set requirepass test123 OK 查询密码: redis 127.0.0.1:6379> config get requirepass (error) ERR operation not permitted 密码验证: redis 127.0.0.1:6379> auth test123 OK 再次查询: redis 127.0.0.1:6379> config get requirepass 1) "requirepass" 2) "test123"
注:如果配置文件中没添加密码 那么redis重启后,密码失效;
3.2 远程连接Redis:
远程连接也是有两种方式:
- 登录的时候加上密码验证:
[root@BrianZhu redis-4.0.8]# src/redis-cli -p 6379 -a test123 127.0.0.1:6379> CONFIG GET requirepass 1) "requirepass" 2) "test123" 127.0.0.1:6379>
- 登录以后在使用auth进行验证
[root@BrianZhu redis-4.0.8]# src/redis-cli 127.0.0.1:6379> CONFIG GET requirepass (error) NOAUTH Authentication required. 127.0.0.1:6379> auth test123 OK 127.0.0.1:6379> CONFIG GET requirepass 1) "requirepass" 2) "test123" 127.0.0.1:6379>
注:AUTH命令跟其他redis命令一样,是没有加密的;阻止不了攻击者在网络上窃取你的密码;认证层的目标是提供多一层的保护。如果防火墙或者用来保护redis的系统防御外部攻击失败的话,外部用户如果没有通过密码认证还是无法访问redis的。
4.Redis的数据类型
Redis支持五种数据类型:
- 字符串(String)
- 集合(set)
- 列表(list)
- 哈希(Map)
- 有序集合(sorted set)
4.1 字符串(String):
- 是Redis最基本的数据类型,可以理解成与Memcached一样的类型,一个Key对应一个Value。
- 二进制安全的。意思就是Redis的String可以包含任何数据,因为他是以二进制的方式存储的。
- 一个键最大存储512MB。
常用字符串命令具体操作如下:
127.0.0.1:6379> set name "Brian Zhu" OK
127.0.0.1:6379> get name "Brian Zhu"
127.0.0.1:6379> GETRANGE name 0 6 "Brian Z" 127.0.0.1:6379> GETRANGE name 0 -1 "Brian Zhu"
127.0.0.1:6379> GETSET name "Brian" "Brian Zhu"
127.0.0.1:6379> GETBIT name 1 (integer) 1 127.0.0.1:6379> GETBIT name 3 (integer) 0 127.0.0.1:6379> GETBIT oo 1 # oo这个key不存在 (integer) 0 # 当偏移量 OFFSET 比字符串值的长度大,或者 key 不存在时,返回 0 。
127.0.0.1:6379> MGET name 1) "Brian" 127.0.0.1:6379> mget name keys 1) "Brian" 2) "hello world" 127.0.0.1:6379> mget name keys oo 1) "Brian" 2) "hello world" 3) (nil) # 没有的变量返回nil
127.0.0.1:6379> SETBIT name 10086 1 (integer) 0 127.0.0.1:6379> GETBIT name 10086 (integer) 1 127.0.0.1:6379> GETBIT name 100 # 默认被初始为0 (integer) 0
127.0.0.1:6379> SETEX test 60 brian OK 127.0.0.1:6379> TTL test (integer) 54 127.0.0.1:6379> GET test "brian" 127.0.0.1:6379> TTL test (integer) -2 127.0.0.1:6379> GET test (nil) # 设置时间过期,key对应的value也将过期
127.0.0.1:6379> EXISTS job # 查看job是否存在 (integer) 0 127.0.0.1:6379> SETNX job "hahaha" # 设置job (integer) 1 127.0.0.1:6379> SETNX job "nidaye" # 覆盖job失败 (integer) 0 127.0.0.1:6379> GET job # 查看job值还是原来的值 "hahaha"
127.0.0.1:6379> GET job "hahaha" 127.0.0.1:6379> SETRANGE job 2 "nidaye" (integer) 8 127.0.0.1:6379> GET job "hanidaye"
127.0.0.1:6379> GET job "hanidaye" 127.0.0.1:6379> STRLEN job (integer) 8
127.0.0.1:6379> mset key1 brian key2 18 OK 127.0.0.1:6379> get key1 "brian" 127.0.0.1:6379> get key2 "18"
127.0.0.1:6379> MSETNX key1 brian key2 19 # key1 和key2存在创建失败 (integer) 0 127.0.0.1:6379> MSETNX key3 jack key4 19 (integer) 1 127.0.0.1:6379> GET key3 "jack" 127.0.0.1:6379> GET key4 "19"
127.0.0.1:6379> PSETEX test1 10000 "100000000" OK 127.0.0.1:6379> PTTL test1 (integer) 8092 127.0.0.1:6379> GET test1 "100000000" 127.0.0.1:6379> PTTL test1 (integer) -2 127.0.0.1:6379> GET test1 (nil)
127.0.0.1:6379> SET number 100 OK 127.0.0.1:6379> INCR number (integer) 101 127.0.0.1:6379> get number "101"
127.0.0.1:6379> GET number "101" 127.0.0.1:6379> INCRBY number 100 (integer) 201 127.0.0.1:6379> GET number "201"
127.0.0.1:6379> GET number "201" 127.0.0.1:6379> INCRBYFLOAT number 100.9999 "301.99990000000000001" 127.0.0.1:6379> GET number "301.99990000000000001"
127.0.0.1:6379> GET number "100" 127.0.0.1:6379> DECR number (integer) 99 127.0.0.1:6379> GET number "99"
127.0.0.1:6379> GET number "99" 127.0.0.1:6379> DECRBY number 10 (integer) 89 127.0.0.1:6379> GET number "89"
127.0.0.1:6379> GET job "hanidaye" 127.0.0.1:6379> APPEND job "niyade" (integer) 14 127.0.0.1:6379> GET job "hanidayeniyade" 127.0.0.1:6379> APPEND ll poip (integer) 4 127.0.0.1:6379> GET ll "poip"
4.2 集合(Set):
- Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
- Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
- 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用集合命令具体操作如下:
127.0.0.1:6379> SADD myset "hello" (integer) 1 127.0.0.1:6379> SADD myset "foo" (integer) 1 127.0.0.1:6379> SADD myset "hello" (integer) 0 127.0.0.1:6379> SMEMBERS myset 1) "foo" 2) "hello"
127.0.0.1:6379> SCARD myset (integer) 2
127.0.0.1:6379> SMEMBERS myset 1) "foo" 2) "hello" 127.0.0.1:6379> SMEMBERS brian 1) "foo" 2) "fo" 3) "nihao" 127.0.0.1:6379> SDIFF myset brian 1) "hello"
127.0.0.1:6379> SMEMBERS myset 1) "foo" 2) "hello" 127.0.0.1:6379> SMEMBERS brian 1) "foo" 2) "fo" 3) "nihao" 127.0.0.1:6379> SINTER myset brian 1) "foo"
127.0.0.1:6379> SDIFFSTORE myset2 brian myset (integer) 2 127.0.0.1:6379> SMEMBERS myset2 1) "fo" 2) "nihao"
127.0.0.1:6379> SINTERSTORE myset3 brian myset (integer) 1 127.0.0.1:6379> SMEMBERS myset3 1) "foo"
127.0.0.1:6379> SISMEMBER brian fo # 存在 (integer) 1 127.0.0.1:6379> SISMEMBER brian do # 不存在 (integer) 0
127.0.0.1:6379> SMEMBERS myset3 1) "foo" 127.0.0.1:6379> SMEMBERS myset 1) "foo" 2) "hello"
127.0.0.1:6379> SMOVE myset foo foo (integer) 1 127.0.0.1:6379> SMEMBERS myset 1) "hello" 127.0.0.1:6379> SMEMBERS foo 1) "foo"
127.0.0.1:6379> SMEMBERS brian 1) "foo" 2) "fo" 3) "nihao" 127.0.0.1:6379> SPOP brian "nihao" 127.0.0.1:6379> SMEMBERS brian 1) "foo" 2) "fo"
127.0.0.1:6379> SRANDMEMBER brian "foo" 127.0.0.1:6379> SRANDMEMBER brian "foo" 127.0.0.1:6379> SRANDMEMBER brian "fo"
127.0.0.1:6379> SMEMBERS brian 1) "fo" 2) "wwwwwww" 3) "a" 4) "hhahaha" 5) "foo" 6) "d" 7) "b" 8) "c" 127.0.0.1:6379> 127.0.0.1:6379> SREM brian wwwwwww d (integer) 2 127.0.0.1:6379> SMEMBERS brian 1) "fo" 2) "a" 3) "hhahaha" 4) "foo" 5) "b" 6) "c"
127.0.0.1:6379> SMEMBERS myset 1) "foo" 2) "a" 3) "c" 4) "hello" 127.0.0.1:6379> SMEMBERS brian 1) "fo" 2) "a" 3) "hhahaha" 4) "foo" 5) "b" 6) "c" 127.0.0.1:6379> SUNION brian myset 1) "fo" 2) "a" 3) "hello" 4) "hhahaha" 5) "foo" 6) "b" 7) "c"
127.0.0.1:6379> SUNIONSTORE mysets brian myset (integer) 7 127.0.0.1:6379> SMEMBERS mysets 1) "fo" 2) "a" 3) "hello" 4) "hhahaha" 5) "foo" 6) "b" 7) "c"
4.3 列表(List):
- Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
- 一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
常用列表命令具体操作如下:
127.0.0.1:6379> LPUSH mylist "hello" (integer) 1 127.0.0.1:6379> LPUSH mylist "hello" "world" (integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1 1) "world" 2) "hello" 3) "hello" 127.0.0.1:6379> LRANGE mylist 0 3 1) "world" 2) "hello" 3) "hello" 127.0.0.1:6379> LRANGE mylist 0 4 1) "world" 2) "hello" 3) "hello" 127.0.0.1:6379> LRANGE mylist 0 1 1) "world" 2) "hello"
127.0.0.1:6379> LPUSHX mylist nihao (integer) 4 127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "world" 3) "hello" 4) "hello"
127.0.0.1:6379> LREM mylist -2 hello (integer) 2 127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "world"
127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "world" 127.0.0.1:6379> LSET mylist 1 hahaha OK 127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "hahaha"
127.0.0.1:6379> RPOP mylist "hahaha"
127.0.0.1:6379> RPOPLPUSH mylist mylist2 "dd" 127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "aa" 3) "bb" 4) "cc" 127.0.0.1:6379> LRANGE mylist2 0 -1 1) "dd"
127.0.0.1:6379> RPUSH mylist "aa" "bb" "cc" "dd" (integer) 5 127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "aa" 3) "bb" 4) "cc" 5) "dd"
127.0.0.1:6379> RPUSHX mylist2 "nihaoya" (integer) 2 127.0.0.1:6379> LRANGE mylist2 0 -1 1) "dd" 2) "nihaoya"
127.0.0.1:6379> LRANGE mylist 0 -1 1) "nihao" 2) "aa" 3) "bb" 4) "cc" 127.0.0.1:6379> LPOP mylist "nihao" 127.0.0.1:6379> LRANGE mylist 0 -1 1) "aa" 2) "bb" 3) "cc"
127.0.0.1:6379> LRANGE mylist 0 -1 1) "aa" 2) "bb" 3) "cc" 127.0.0.1:6379> LLEN mylist (integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1 1) "aa" 2) "bb" 3) "cc" 127.0.0.1:6379> LINDEX mylist 2 "cc"
4.4 哈希(Map):
- 是一个键值对的集合
- 是一个String类型的field和value的映射表,hash特别适合用于存储对象
- Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)
常用哈希命令具体操作如下:
127.0.0.1:6379> HSET test2 name jack (integer) 1
127.0.0.1:6379> HGET test2 name "jack"
127.0.0.1:6379> HMSET names one brian two jack OK
127.0.0.1:6379> HMGET names one two 1) "brian" 2) "jack"
127.0.0.1:6379> HDEL names two (integer) 1 127.0.0.1:6379> HGET name two (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> HEXISTS names two # 不存在 (integer) 0 127.0.0.1:6379> HEXISTS names one # 存在 (integer) 1
127.0.0.1:6379> HGETALL names 1) "one" # 哈希表key 2) "brian" # key对应的值
127.0.0.1:6379> HSET ages one 100 (integer) 1 127.0.0.1:6379> HINCRBY ages one 10 (integer) 110 127.0.0.1:6379> HGET ages one "110"
127.0.0.1:6379> HGET ages one "110" 127.0.0.1:6379> HINCRBYFLOAT ages one 10.98 "120.98" 127.0.0.1:6379> HGET ages one "120.98"
127.0.0.1:6379> HMSET ages one 100 two aini three aini100 OK 127.0.0.1:6379> HKEYS ages 1) "one" 2) "two" 3) "three"
127.0.0.1:6379> HLEN ages (integer) 3
127.0.0.1:6379> HSETNX ages one "1000" # 存在无法创建 (integer) 0 127.0.0.1:6379> HSETNX ages frou "youyouyou" # 不存在创建 (integer) 1 127.0.0.1:6379> HGET ages one "100" 127.0.0.1:6379> HGET ages frou "youyouyou"
127.0.0.1:6379> HVALS ages 1) "100" 2) "aini" 3) "aini100" 4) "youyouyou"
4.5 有序集合(Sorted set):
- Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
- 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
- 有序集合的成员是唯一的,但分数(score)却可以重复。
- 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1).
- 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用有序集合命令具体操作如下:
127.0.0.1:6379> ZADD myzset 1 "one" (integer) 1 127.0.0.1:6379> ZADD myzset 1 "uno" (integer) 1 127.0.0.1:6379> ZADD myzset 2 "two" 3 "three" (integer) 2 127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES 1) "one" 2) "1" 3) "uno" 4) "1" 5) "two" 6) "2" 7) "three" 8) "3"
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES 1) "one" 2) "1" 3) "uno" 4) "1" 5) "two" 6) "2" 7) "three" 8) "3" 127.0.0.1:6379> ZCARD myzset (integer) 4
127.0.0.1:6379> ZADD myzset 1 "hello" (integer) 1 127.0.0.1:6379> ZADD myzset 1 "foo" (integer) 1 127.0.0.1:6379> ZADD myzset 2 "world" 3 "bar" (integer) 2 127.0.0.1:6379> ZCOUNT myzset 1 3 (integer) 8
127.0.0.1:6379> ZADD myzset1 1 "one" (integer) 1 127.0.0.1:6379> ZADD myzset1 2 "two" (integer) 1 127.0.0.1:6379> ZINCRBY myzset1 2 "one" "3" 127.0.0.1:6379> ZRANGE myzset1 0 -1 WITHSCORES 1) "two" 2) "2" 3) "one" 4) "3"
# 有序集 mid_test redis 127.0.0.1:6379> ZADD mid_test 70 "Li Lei" (integer) 1 redis 127.0.0.1:6379> ZADD mid_test 70 "Han Meimei" (integer) 1 redis 127.0.0.1:6379> ZADD mid_test 99.5 "Tom" (integer) 1 # 另一个有序集 fin_test redis 127.0.0.1:6379> ZADD fin_test 88 "Li Lei" (integer) 1 redis 127.0.0.1:6379> ZADD fin_test 75 "Han Meimei" (integer) 1 redis 127.0.0.1:6379> ZADD fin_test 99.5 "Tom" (integer) 1 # 交集 redis 127.0.0.1:6379> ZINTERSTORE sum_point 2 mid_test fin_test (integer) 3 # 显示有序集内所有成员及其分数值 redis 127.0.0.1:6379> ZRANGE sum_point 0 -1 WITHSCORES 1) "Han Meimei" 2) "145" 3) "Li Lei" 4) "158" 5) "Tom" 6) "199"
redis 127.0.0.1:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e (integer) 5 redis 127.0.0.1:6379> ZADD myzset 0 f 0 g (integer) 2 redis 127.0.0.1:6379> ZLEXCOUNT myzset - + (integer) 7 redis 127.0.0.1:6379> ZLEXCOUNT myzset [b [f (integer) 5
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示整个有序集成员 1) "jack" 2) "3500" 3) "tom" 4) "5000" 5) "boss" 6) "10086" redis 127.0.0.1:6379> ZRANGE salary 1 2 WITHSCORES # 显示有序集下标区间 1 至 2 的成员 1) "tom" 2) "5000" 3) "boss" 4) "10086" redis 127.0.0.1:6379> ZRANGE salary 0 200000 WITHSCORES # 测试 end 下标超出最大下标时的情况 1) "jack" 2) "3500" 3) "tom" 4) "5000" 5) "boss" 6) "10086" redis > ZRANGE salary 200000 3000000 WITHSCORES # 测试当给定区间不存在于有序集时的情况 (empty list or set)
redis 127.0.0.1:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g (integer) 7 redis 127.0.0.1:6379> ZRANGEBYLEX myzset - [c 1) "a" 2) "b" 3) "c" redis 127.0.0.1:6379> ZRANGEBYLEX myzset - (c 1) "a" 2) "b" redis 127.0.0.1:6379> ZRANGEBYLEX myzset [aaa (g 1) "b" 2) "c" 3) "d" 4) "e" 5) "f"
redis 127.0.0.1:6379> ZADD salary 2500 jack # 测试数据 (integer) 0 redis 127.0.0.1:6379> ZADD salary 5000 tom (integer) 0 redis 127.0.0.1:6379> ZADD salary 12000 peter (integer) 0 redis 127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf # 显示整个有序集 1) "jack" 2) "tom" 3) "peter" redis 127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf WITHSCORES # 显示整个有序集及成员的 score 值 1) "jack" 2) "2500" 3) "tom" 4) "5000" 5) "peter" 6) "12000" redis 127.0.0.1:6379> ZRANGEBYSCORE salary -inf 5000 WITHSCORES # 显示工资 <=5000 的所有成员 1) "jack" 2) "2500" 3) "tom" 4) "5000" redis 127.0.0.1:6379> ZRANGEBYSCORE salary (5000 400000 # 显示工资大于 5000 小于等于 400000 的成员 1) "peter"
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示所有成员及其 score 值 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZRANK salary tom # 显示 tom 的薪水排名,第二 (integer) 1
# 测试数据 redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "baidu.com" 4) "9" 5) "google.com" 6) "10" # 移除单个元素 redis 127.0.0.1:6379> ZREM page_rank google.com (integer) 1 redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "baidu.com" 4) "9" # 移除多个元素 redis 127.0.0.1:6379> ZREM page_rank baidu.com bing.com (integer) 2 redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES (empty list or set) # 移除不存在元素 redis 127.0.0.1:6379> ZREM page_rank non-exists-element (integer) 0
redis 127.0.0.1:6379> ZADD myzset 0 aaaa 0 b 0 c 0 d 0 e (integer) 5 redis 127.0.0.1:6379> ZADD myzset 0 foo 0 zap 0 zip 0 ALPHA 0 alpha (integer) 5 redis 127.0.0.1:6379> ZRANGE myzset 0 -1 1) "ALPHA" 2) "aaaa" 3) "alpha" 4) "b" 5) "c" 6) "d" 7) "e" 8) "foo" 9) "zap" 10) "zip" redis 127.0.0.1:6379> ZREMRANGEBYLEX myzset [alpha [omega (integer) 6 redis 127.0.0.1:6379> ZRANGE myzset 0 -1 1) "ALPHA" 2) "aaaa" 3) "zap" 4) "zip"
redis 127.0.0.1:6379> ZADD salary 2000 jack (integer) 1 redis 127.0.0.1:6379> ZADD salary 5000 tom (integer) 1 redis 127.0.0.1:6379> ZADD salary 3500 peter (integer) 1 redis 127.0.0.1:6379> ZREMRANGEBYRANK salary 0 1 # 移除下标 0 至 1 区间内的成员 (integer) 2 redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 有序集只剩下一个成员 1) "tom" 2) "5000"
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示有序集内所有成员及其 score 值 1) "tom" 2) "2000" 3) "peter" 4) "3500" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZREMRANGEBYSCORE salary 1500 3500 # 移除所有薪水在 1500 到 3500 内的员工 (integer) 2 redis> ZRANGE salary 0 -1 WITHSCORES # 剩下的有序集成员 1) "jack" 2) "5000"
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 递增排列 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列 1) "jack" 2) "5000" 3) "tom" 4) "4000" 5) "peter" 6) "3500"
redis 127.0.0.1:6379> ZADD salary 10086 jack (integer) 1 redis > ZADD salary 5000 tom (integer) 1 redis 127.0.0.1:6379> ZADD salary 7500 peter (integer) 1 redis 127.0.0.1:6379> ZADD salary 3500 joe (integer) 1 redis 127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf # 逆序排列所有成员 1) "jack" 2) "peter" 3) "tom" 4) "joe" redis 127.0.0.1:6379> ZREVRANGEBYSCORE salary 10000 2000 # 逆序排列薪水介于 10000 和 2000 之间的成员 1) "peter" 2) "tom" 3) "joe"
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 测试数据 1) "jack" 2) "2000" 3) "peter" 4) "3500" 5) "tom" 6) "5000" redis 127.0.0.1:6379> ZREVRANK salary peter # peter 的工资排第二 (integer) 1 redis 127.0.0.1:6379> ZREVRANK salary tom # tom 的工资最高 (integer) 0
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 测试数据 1) "tom" 2) "2000" 3) "peter" 4) "3500" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZSCORE salary peter # 注意返回值是字符串 "3500"
redis 127.0.0.1:6379> ZRANGE programmer 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" redis 127.0.0.1:6379> ZRANGE manager 0 -1 WITHSCORES 1) "herry" 2) "2000" 3) "mary" 4) "3500" 5) "bob" 6) "4000" redis 127.0.0.1:6379> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 # 公司决定加薪。。。除了程序员。。。 (integer) 6 redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" 7) "herry" 8) "6000" 9) "mary" 10) "10500" 11) "bob" 12) "12000"
5.Redis的发布订阅
- Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
- Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
具体实例:
创建订阅频道名为 redisChat:
127.0.0.1:6379> SUBSCRIBE redisChat Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1
现在,我们先重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。
# 发布的两次消息 127.0.0.1:6379> PUBLISH redisChat "hello world" (integer) 1 127.0.0.1:6379> PUBLISH redisChat "Nice to meet you" (integer) 1 # 订阅者接收到的信息 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1 1) "message" 2) "redisChat" 3) "hello world" 1) "message" 2) "redisChat" 3) "Nice to meet you"
6.Redis的HyperLogLog
- Redis HyperLogLog是用来做基数统计的算法。
- 优点是:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
- 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
注:因为HyperLogLog只会根据输入元素来计算基数,而不会存储输入元素本身,因此不会返回输入的各个元素。
基数是什么?
对于["abc", "abc", "2", "3"],基数是["abc", "2", "3"],个数是3.
具体实例如下:
127.0.0.1:6379> pfadd jsh redis (integer) 1 127.0.0.1:6379> pfadd jsh redis (integer) 0 127.0.0.1:6379> pfadd jsh mongodb (integer) 1 127.0.0.1:6379> pfadd jsh rabbitmq (integer) 1 127.0.0.1:6379> pfcount jsh (integer) 3 127.0.0.1:6379> pfadd jsh2 redis (integer) 1 127.0.0.1:6379> pfadd jsh2 a (integer) 1 127.0.0.1:6379> pfcount jsh2 (integer) 2 127.0.0.1:6379> pfmerge jsh jsh2 OK 127.0.0.1:6379> pfcount jsh (integer) 4 127.0.0.1:6379> pfcount jsh2 (integer) 2
注:
- pfadd key ele [ele2 ...]:添加指定元素到HyperLogLog中。
- pfcount key: 返回给定HyperLogLog的基数估算值。
- pfmerge destkey srckey [srckey2....]:讲多个HyperLogLog合并到一个第一个HyperLogLog中。
7.Redis的事务
Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务
- 命令入队
- 执行事务
以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET qq-name "python love you" QUEUED 127.0.0.1:6379> GET qq-name QUEUED 127.0.0.1:6379> SADD tag "java" "php" "c++" QUEUED 127.0.0.1:6379> SMEMBERS tag QUEUED 127.0.0.1:6379> EXEC 1) OK 2) "python love you" 3) (integer) 3 4) 1) "c++" 2) "java" 3) "php"
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
比如:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a aaa QUEUED 127.0.0.1:6379> SET b bbb QUEUED 127.0.0.1:6379> SET c ccc QUEUED 127.0.0.1:6379> EXEC 1) OK 2) OK 3) OK
注:如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。
redis 事务的相关命令:
- DISCARD :取消事务,放弃执行事务块内的所有命令。
- EXEC :执行所有事务块内的命令。
- MULTI :标记一个事务块的开始。
- UNWATCH :取消 WATCH 命令对所有 key 的监视。
- WATCH key [key ...] :监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
8.Redis的脚本
Redis 脚本使用 Lua 解释器来执行脚本。执行脚本的常用命令为 EVAL。基本语法:
EVAL script numkeys key [key ...] arg [arg ...]
具体实例:
127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first seconde 1) "key1" 2) "key2" 3) "first" 4) "seconde"
9.Redis的数据备份与恢复
9.1 备份数据:
Redis SAVE 命令用于创建当前数据库的备份
语法:
127.0.0.1:6379> SAVE
具体实例:
127.0.0.1:6379> SAVE OK 127.0.0.1:6379>
注:该命令将在 redis 安装目录中创建dump.rdb文件
9.2 恢复数据:
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令,如下所示:
127.0.0.1:6379> CONFIG GET dir 1) "dir" 2) "/root/redis-4.0.8" 127.0.0.1:6379>
以上命令 CONFIG GET dir 输出的 redis 安装目录为:/root/redis-4.0.8
9.3 后台执行备份:
创建 redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行。
127.0.0.1:6379> BGSAVE Background saving started 127.0.0.1:6379>
10.Redis数据库操作
Redis中,一共有16个数据库,分别是0~15,一般情况下,进入数据库默认编号是0
如果我们要进入指定数据库,可以用select语句:
切换到编号为6的数据库:
127.0.0.1:6379> SELECT 6 OK 127.0.0.1:6379[6]>
查看数据库中所有的键值:
# 因为编号6 中没有数据 所以先临时新建几个 127.0.0.1:6379[6]> SET a 1 OK 127.0.0.1:6379[6]> SET b 2 OK 127.0.0.1:6379[6]> SET c 3 OK 127.0.0.1:6379[6]> KEYS * 1) "b" 2) "a" 3) "c"
返回当前数据库中所有key的数目: dbsize
删除当前数据库中的所有key: flushdb
清空所有数据库中的所有key: flushall
把当前数据库中的key转移到指定数据库:move a aim_db,例:
127.0.0.1:6379[6]> set z qqq OK 127.0.0.1:6379[6]> MOVE z 0 (integer) 1 127.0.0.1:6379[6]> SELECT 0 OK 127.0.0.1:6379> GEt z "qqq"
11.Redis管道技术(哈哈 还在学习中)
12.Redis分区
分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。
12.1 分区的优势:
- 通过利用多台计算机内存的和值,允许我们构造更大的数据库。
- 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。
12.2 分区的劣势:
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
- 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。
12.3 分区的类型:
Redis 有两种类型分区。 假设有4个Redis实例 R0,R1,R2,R3,和类似user:1,user:2这样的表示用户的多个key,对既定的key有多种不同方式来选择这个key存放在哪个实例中。也就是说,有不同的系统来映射某个key到某个Redis服务。
- 范围分区:
最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例。
比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推。
这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各 种对象的映射表,通常对Redis来说并非是好的方法。
- 哈希分区:
另外一种分区方法是hash分区。这对任何key都适用,也无需是object_name:这种形式,像下面描述的一样简单:
-
- 用一个hash函数将key转换为一个数字,比如使用crc32 hash函数。对key foobar执行crc32(foobar)会输出类似93024922的整数。
- 对这个整数取模,将其转化为0-3之间的数字,就可以将这个整数映射到4个Redis实例中的一个了。93024922 % 4 = 2,就是说key foobar应该被存到R2实例中。注意:取模操作是取除的余数,通常在多种编程语言中用%操作符实现。
13.Redis性能测试
Redis 性能测试是通过同时执行多个命令实现的。
语法:
redis-benchmark [option] [option value]
具体实例:
以下实例同时执行 10000 个请求来检测性能:
[root@BrianZhu redis-4.0.8]# src/redis-benchmark -n 10000 -q PING_INLINE: 94339.62 requests per second PING_BULK: 92592.59 requests per second SET: 91743.12 requests per second GET: 90090.09 requests per second INCR: 97087.38 requests per second LPUSH: 96153.84 requests per second RPUSH: 96153.84 requests per second LPOP: 97087.38 requests per second RPOP: 97087.38 requests per second SADD: 96153.84 requests per second HSET: 93457.95 requests per second SPOP: 97087.38 requests per second LPUSH (needed to benchmark LRANGE): 94339.62 requests per second LRANGE_100 (first 100 elements): 95238.10 requests per second LRANGE_300 (first 300 elements): 95238.10 requests per second LRANGE_500 (first 450 elements): 96153.84 requests per second LRANGE_600 (first 600 elements): 78740.16 requests per second MSET (10 keys): 83333.34 requests per second
14.Redis关闭持久化(单纯的做缓存)
数据持久化是Redis不同于其他缓存的一个特性,具有明显的有点。但如不希望持久化数据,只作为普通的缓存用,如memcache
方法:
将配置文件中关于save配置信息全部注释,如下:
#save 900 1 #save 300 10 #save 60 10000
或执行操作命令:
CONFIG SET save ""
执行命令后,无需重启即可生效
15.Redis可视化工具
都到这里了 肯定命令都已经玩腻了吧 现在来新菜了 那就是Redis的可视化工具 它的名字叫:RedisDesktopManager 下载地址:https://redisdesktop.com/download
安装连接就很简单了 和windows的其他软件一样 下一步 下一步就好了 软件是全英文的 但是看懂也不需要太好的英文水平 其实我就是个英文盲 下面就贴几张图 结束吧