Redis入门
Linux安装
下载地址 http://download.redis.io/releases/redis-5.0.7.tar.gz
安装步骤
1、下载获得 redis-5.0.7.tar.gz 后将它放到我们Linux的目录下 /opt
2、/opt 目录下,解压命令 : tar -zxvf redis-5.0.7.tar.gz
3、解压完成后出现文件夹:redis-5.0.7
4、进入目录: cd redis-5.0.7
5、在 redis-5.0.7 目录下执行 make 命令
运行make命令时故意出现的错误解析:
1. 安装gcc (gcc是linux下的一个编译程序,是c程序的编译工具)
能上网: yum install gcc-c++
版本测试: gcc-v
2. 二次make
3. Jemalloc/jemalloc.h: 没有那个文件或目录
运行 make distclean 之后再make
4. Redis Test(可以不用执行)
6、如果make完成后继续执行 make install
7、查看默认安装目录:usr/local/bin
/usr 这是一个非常重要的目录,类似于windows下的Program Files,存放用户的程序
8、拷贝配置文件(备用)
cd /usr/bin
ls -l
# 在redis的解压目录下备份redis.conf
mkdir myredis
cp redis.conf myredis
# 拷一个备份,养成良好的习惯,我们就修改这个文件
# 修改配置保证可以后台应用
vim redis.conf
daemonize 设置yes或者no区别
-
daemonize:yes
- redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfifile设置的文件中,此时redis将一直运行,除非手动kill该进程。
-
daemonize:no
- 当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。
9、测试一下!
# 我使用的是宝塔下载,所以及宝塔启动了
[root@VM-0-5-centos ~]# cd /usr/bin
# redis客户端连接===> 观察地址的变化,如果连接ok,是直接连上的,redis默认端口号 6379
[root@VM-0-5-centos bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set k1 hellword
OK
127.0.0.1:6379> get k1
"hellword"
# 【shell】ps显示系统当前进程信息
[root@VM-0-5-centos /]# ps -ef | grep redis
redis 7955 1 0 00:12 ? 00:00:00 /www/server/redis/src/redis-server 127.0.0.1:6379
root 8322 4825 0 00:13 pts/0 00:00:00 redis-cli -p 6379
root 15654 10426 0 00:16 pts/2 00:00:00 grep --color=auto redis
# 【redis】关闭连接
127.0.0.1:6379> shutdown
not connected> exit
# 【shell】ps显示系统当前进程信息
[root@192 myredis]# ps -ef|grep redis
root 16140 16076 0 04:53 pts/2 00:00:00 grep --color=auto redis
基础说明
准备工作:开启redis服务,客户端连接
redis压力测试工具-----Redis-benchmark
Redis-benchmark是官方自带的Redis性能测试工具,可以有效的测试Redis服务的性能。
redis 性能测试工具可选参数如下所示:
# 测试一:100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性 能
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
# 测试出来的所有命令只举例一个!
====== SET ======
100000 requests completed in 1.88 seconds # 对集合写入测试
100 parallel clients # 每次请求有100个并发客户端
3 bytes payload # 每次写入3个字节的数据,有效载荷
keep alive: 1 # 保持一个连接,一台服务器来处理这些请求
17.05% <= 1 milliseconds
97.35% <= 2 milliseconds
99.97% <= 3 milliseconds
100.00% <= 3 milliseconds # 所有请求在 3 毫秒内完成 53248.14 requests per second # 每秒处理 53248.14 次请求
基础数据库常识
默认16个数据库,类似数组下标从零开始,初始默认为零号库
查看 redis.conf ,里面有默认的配置
databases 16
# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16
Select命令切换数据库
127.0.0.1:6379> select 7
OK
127.0.0.1:6379[7]>
# 不同的库可以存不同的数据
Dbsize查看当前数据库的key数量
127.0.0.1:6379> select 7
OK
127.0.0.1:6379[7]> dbsize
(integer) 0
127.0.0.1:6379[7]> SELECT 0
OK
127.0.0.1:6379> DBSIZE
(integer) 1
127.0.0.1:6379> KEYS *
1) "k1"
Flushdb:清空当前库
Flushall:清空全部的库
127.0.0.1:6379> DBSIZE
(integer) 1
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> DBSIZE
(integer) 0
为什么默认端口是6379呢? 粉丝效应
redis是单线程的
我们首先要明白,Redis很快!官方表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了!
6Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV数据库 Memcached 差!
Redis为什么单线程还这么快?
1.误区: 高性能的服务器一定是多线程的?
2.误区: 多线程(CPU上下文切换) 一定比单线程效率高
CPU>内存>硬盘速度(juc)
核心: redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!) ,对于内存系统来说,如果没有上下文切换效率就是最高的! 多次读写对都是在一个CPU上的,在内存情况下,这个就是最佳的方案
五大数据类型
Redis是一个开放源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存和消息代理。它支持数
据结构,例如字符串,哈希,列表,集合,带范围查询的排序集合,位图,超日志,带有半径查询和流
的地理空间索引。Redis具有内置的复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过
Redis Sentinel和Redis Cluster自动分区提供了高可用性。
String(字符串类型)
String是redis最基本的类型,你可以理解成Memcached一模一样的类型,一个key对应一个value
String类型时二进制安全的,意思是redis的String可以包含任何数据,比如jpg图片或者序列化的对象。
String类型时redis最基本的数据类型,一个redis中字符串value最多可以是512M
Hash(哈希,类似Java里的Map)
Redis hash是一个键值对集合
Redis hash是一个String类型的field和value的映射表,hash特别适合用于存储对象。
类似于Java里面的Map<String, Object>
List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)
它的底层实际是个链表
Set(集合)
Redis的Set是String类型的无序集合,它是通过HashTable实现的!
Zset(sorted set:有序集合)
Redis zset和set一样,也是String类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数
Redis正是通过分数来为集合的成员进行从小到大的排序,zset的成员是唯一的,但是分数(Score)且可以重复。
Redis键(key)
1.exists name # 判断当前key是否存在 存在为1 反之为0
2.move name # 移除当前key
3.expire name 10 # 设置key的过期时间,单位是秒
4.ttl name # 查看当前key的剩余时间
5.type name # 查看key的类型
127.0.0.1:6379> set name bingning
OK
127.0.0.1:6379> KEYS *
1) "name"
# exists key 的名字,判断某个key是否存在
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
#移除当前库中的key
127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> key *
127.0.0.1:6379> keys *
(empty array)
# 为给点key设置生存时间, 时间到了 他会被自动删除
# ttl key 查看还有多少秒过期, -1表示永不过期,-2表示已过期
127.0.0.1:6379> EXPIRE name 20
(integer) 1
127.0.0.1:6379> TTL name
(integer) 15
127.0.0.1:6379> TTL name
(integer) 13
127.0.0.1:6379> TTL name
(integer) -2
127.0.0.1:6379> keys *
(empty array)
# type key 查看key的类型
127.0.0.1:6379> set name bingnign
OK
127.0.0.1:6379> TYPE name
string
String
单值Value
常规命令说明:
-
append name “shanjiao” # 追加字符串,如果当前key不存在相当于setkey
-
strlen name # 查看指定key的长度
-
incr views # views自增1
-
decr views # views自减1
-
incrby views 10 # 自定义设置自增步长
-
decrby views 5 # 自定义设置自减步长
-
getrange 获取指定区间范围内的值
-
setrange 设置指定区间范围内的值,格式是setrange key值
-
setex(set with expire)键秒值 setnx(set if not exist)
-
mset Mset 命令用于同时设置一个或多个 key-value 对。
-
mget Mget 命令返回所有(一个或多个)给定 key 的值。
-
msetnx 当所有 key 都成功设置,返回 1
-
这里的key是一个巧妙的设计: user:{id} {filed},如此设计在redis中完全可以
-
getset # 先get再set
#===================================================
# set、get、del、append、strlen
#===================================================
127.0.0.1:6379> set name bingnign # 设置值
OK
127.0.0.1:6379> get name # 获取值
"bingnign"
127.0.0.1:6379> DEL name # 删除值
(integer) 1
127.0.0.1:6379> keys * # 查看全部的key
(empty array)
127.0.0.1:6379> EXISTS name # 查看key是否存在
(integer) 0
127.0.0.1:6379> append name "hello" # 对不存在的key进行Append,等同于set name "hello"
(integer) 5 #字符串长度
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> append name "-4243" # 对已存在的字符串进行Append
(integer) 10 # 长度从5字符增加到10个字符
127.0.0.1:6379> get name
"hello-4243"
127.0.0.1:6379> STRLEN name # 获取字符串长度
(integer) 10
#===================================================
# incr、decr 一定要是数字才能进行加减,+1 和 -1。
# incrby、decrby 命令将 key 中储存的数字加上指定的增量值。
#===================================================
127.0.0.1:6379> set views 0 #设置游览量为0
OK
127.0.0.1:6379> INCR views #游览 +1
(integer) 1
127.0.0.1:6379> INCR views # 游览 +1
(integer) 2
127.0.0.1:6379> decr views # 游览减1
(integer) 1
127.0.0.1:6379> incrby views 19 # 指定游览 +19
(integer) 20
127.0.0.1:6379> decrby views 20 # 指定游览减19
(integer) 0
#===================================================
# range [范围] # getrange 获取指定区间范围内的值,类似between...and的关系,从零到负一表示全部
#===================================================
127.0.0.1:6379> set key2 fdshhe23
OK
127.0.0.1:6379> getrange key2 0 -1 # 获取全部范围的值
"fdshhe23"
127.0.0.1:6379> getrange key2 0 5 # 从第一个位置开始,获取0-5的值
"fdshhe"
#===================================================
# setrange 设置指定区间范围内的值,格式是setrange key值 具体值
#===================================================
127.0.0.1:6379> get key2
"fdshhe23"
127.0.0.1:6379> SETRANGE key2 1 fds # 替换值,从第二个位置开始
(integer) 8
127.0.0.1:6379> get key2
"ffdshe23"
127.0.0.1:6379> SETRANGE key2 3 fdsetrtd # 替换值超过了已有值自动添加
(integer) 11
127.0.0.1:6379> get key2
"ffdfdsetrtd"
#===================================================
# setex(set with expire)键秒值
# setnx(set if not exist)
#===================================================
127.0.0.1:6379> setex key3 60 expire # 设置过期时间
OK
127.0.0.1:6379> ttl key3 # 查看剩余的世界
(integer) 53
127.0.0.1:6379> get key3
"expire"
127.0.0.1:6379> setnx mykey "redis" # 如果不存在就设置,成功返回1
(integer) 1
127.0.0.1:6379> setnx mykey "mongodb" # 如果存在就设置,失败返回0
(integer) 0
127.0.0.1:6379> get mykey
"redis"
#===================================================
# mset Mset 命令用于同时设置一个或多个 key-value 对。
# mget Mget 命令返回所有(一个或多个)给定 key 的值。
# 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。
# msetnx 当所有 key 都成功设置,返回 1 。
# 如果所有给定 key 都设置失败(至少有一个 key 已经存在),那么返回 0 。原子操 作#===================================================
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 k4
1) "v1"
2) "v2"
3) "v3"
4) (nil)
127.0.0.1:6379> msetnx k1 k4 k5 k6 # 原子性操作
(integer) 0
127.0.0.1:6379> get key5
(nil)
# 传统对象缓存
127.0.0.1:6379> set user:1 value
OK
127.0.0.1:6379> get user:1
"value"
# 对象
set user:1 {name:zhangsan,age:3} # 设置一个user:1 对象 的值为json字符来保存一个对象
# 这里的key是一个巧妙的设计: user:{id} {filed},如此设计在redis中完全可以
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
# getset(先get再set)
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379> getset db redis
"mongodb"
127.0.0.1:6379> get db
"redis"
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。
常规key-value缓存应用:
常规计数:微博数,粉丝数等
列表List
Lpush
:将一个或多个值插入到列表头部。(左)rpush
:将一个或多个值插入到列表尾部。(右)lrange
:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。lpop
命令用于移除并返回列表的第一个元素。当列表 key 不存在时,返回 nil 。rpop
移除列表的最后一个元素,返回值为移除的元素。Lindex
,按照索引下标获得元素(-1代表最后一个,0代表是第一个)llen
用于返回列表的长度。lrem key
根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。rpoplpush
移除列表的最后一个元素,并将该元素添加到另一个列表并返回。lset key index value
将列表 key 下标为 index 的元素的值设置为 valuelinsert key before/after pivot value
用于在列表的元素前或者后插入元素。 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
#===================================================
# Lpush:将一个或多个值插入到列表头部。(左)
# rpush:将一个或多个值插入到列表尾部。(右)
# lrange:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
# 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。
# 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此 类推。
#==================================================
127.0.0.1:6379> lpush list "ont"
(integer) 1
127.0.0.1:6379> LPUSH list "tpw" "fed"
(integer) 3
127.0.0.1:6379> rpush list "right"
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "fed"
2) "tpw"
3) "ont"
4) "right"
127.0.0.1:6379> lrange list 0 1
1) "fed"
2) "tpw"
#===================================================
# lpop 命令用于移除并返回列表的第一个元素。当列表 key 不存在时,返回 nil 。
# rpop 移除列表的最后一个元素,返回值为移除的元素。
#===================================================
127.0.0.1:6379> lrange list 0 1
1) "fed"
2) "tpw"
127.0.0.1:6379> LPOP list
"fed"
127.0.0.1:6379> rpop list
"right"
127.0.0.1:6379> lrange list 0 -1
1) "tpw"
2) "ont"
#===================================================
# Lindex,按照索引下标获得元素(-1代表最后一个,0代表是第一个)
#===================================================
127.0.0.1:6379> lindex list 1
"ont"
127.0.0.1:6379> lindex list 0
"tpw"
127.0.0.1:6379> lindex list -1
"ont"
#===================================================
# llen 用于返回列表的长度。
#===================================================
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list "one" "two" "three"
(integer) 3
127.0.0.1:6379> LLEN list
(integer) 3
#===================================================
# lrem key 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
#===================================================
127.0.0.1:6379> lrem mylist 1 "hello"
(integer) 1
127.0.0.1:6379> lrange mylist 0 -1
1) "foo"
#===================================================
# Ltrim key 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区 间之内的元素都将被删除。
#===================================================
127.0.0.1:6379> rpush mylist "hello" "hello1" "hello2" "hello3"
(integer) 4
127.0.0.1:6379> LTRIM mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
#===================================================
# rpoplpush 移除列表的最后一个元素,并将该元素添加到另一个列表并返回。
#===================================================
127.0.0.1:6379> rpush mylist "hello" "foo" "bar"
(integer) 3
127.0.0.1:6379> RPOPLPUSH mylist myotherlist
"bar"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "foo"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "bar"
#===================================================
# lset key index value 将列表 key 下标为 index 的元素的值设置为 value 。
#===================================================
127.0.0.1:6379> exists list # 对空列表(key 不存在)进行List
(integer) 0
127.0.0.1:6379> lset list 0 item # 报错
(error) ERR no such key
127.0.0.1:6379> lpush list "valuel" # 对非空列表进行lset
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "valuel"
127.0.0.1:6379> lset list 0 "new" # 更新值
OK
127.0.0.1:6379> lrange list 0 0
1) "new"
127.0.0.1:6379> liset list 1 "new" # index 超出范围报错
(error) ERR unknown command `liset`, with args beginning with: `list`, `1`, `new`,
#===================================================
# linsert key before/after pivot value 用于在列表的元素前或者后插入元素。
# 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
#===================================================
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "world"
(integer) 2
127.0.0.1:6379> LINsert mylist before "world" "Three"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "Three"
3) "world"
小结
- 他实际上是一个链表,before Bode after, left, right 都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也就代表不存在
- 在两边插入或者改动值,效率最高!中间元素,相对俩手效率会低一点~
消息队列,消息排队!(Lpush Rpop) , 栈 (Lpush Lpop)!
集合Set
-
sadd 将一个或多个成员元素加入到集合中,不能重复
-
smembers 返回集合中的所有的成员。
-
sismember 命令判断成员元素是否是集合的成员。
-
scard,获取集合里面的元素个数
-
srem key value 用于移除集合中的一个或多个成员元素
-
srandmember key 命令用于返回集合中的一个或多个随机元素。
-
spop key 用于移除集合中的指定 key 的一个或多个随机元素
-
smove SOURCE DESTINATION MEMBER
-
将指定成员 member 元素从 source 集合移动到 destination 集合。
-
数字集合类
- 差集: sdiff
- 交集: sinter
- 并集: sunion
#===================================================
# sadd 将一个或多个成员元素加入到集合中,不能重复
# smembers 返回集合中的所有的成员。
# sismember 命令判断成员元素是否是集合的成员。
#===================================================
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "kung"
(integer) 1
127.0.0.1:6379> sadd myset "kung" # 集合中已经存在,添加失败
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "kung"
2) "hello"
127.0.0.1:6379> SISMEMBER myset "hello"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "wo"
(integer) 0
# ===================================================
# scard,获取集合里面的元素个数
#===================================================
127.0.0.1:6379> scard myset
(integer) 2
#===================================================
# srem key value 用于移除集合中的一个或多个成员元素
#===================================================
127.0.0.1:6379> srem myset "kung"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
# srandmember key 命令用于返回集合中的一个随机元素。
127.0.0.1:6379> SMEMBERS myset
1) "bingbing"