Redis 学习笔记

摘要:Redis (Remote Dictionary Server) 是一个开源的、基于内存的数据结构存储器,可以被用作数据库、缓存和消息代理。如果你是一名NoSQL的拥护者,你一定会提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,无疑是一种全新思维的注入。所以,你完全可以将Redis融入到你的系统中,它能帮你解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务,你可以通过Redis来进行优化,或者为应用创建些新的功能。在本文中,先从认识Redis开始,一步步编译和安装,再对基本的五种数据类型进行操作,了解Redis的持久化功能和主从配置,最终能使用PHP脚本语言操作Redis。

关于Redis

Redis是一个开源的、基于内存的数据结构存储器,可以被用作数据库、缓存和消息代理。

相较Memcached而言,支持更加丰富的数据结构,包括字符串、哈希、列表、集合、有序集合等,此外还支持将数据持久化到数据库。

MySQL数据库的数据是以文件形式保存在硬盘里边。

Redis也是数据库服务器(但是其不可以保存复杂的信息,其特点是数据较简单,但是速度快)软件,数据是在内存里边保存。

为什么要使用Redis

有的时候一个网站页面的数据在相对一段时间(半天、一天)不发生变化,同时该页面每天还要被许多人访问。

我们把该页面从MySQL里边获得数据放到内存里边,这样既节省MySQL数据库资源、间接还节省服务器资源,同时还会使得网站访问速度加快,提升用户体验。

以下是使用Redis的原因:

① 是一款数据库产品,有数据存储功能
② 高速读取数据(in-memory)
③ 减轻数据库负担,大量节省数据库资源
④ 有集合计算功能(优于普通数据库和同类别产品)
⑤ 多种数据结构支持

什么是Redis

Remote dictionary server (远程数据字典服务)

该软件时意大利人(Antirez)开发的,使用C语言开发的一款内存高速数据库服务软件。

该软件内部有各种非常使用的数据类型:string set(集合) sort set(排序集合) list(列表) hash(哈希) bitmaps(位图) hyperloglogs(基数统计)

该软件有本地持久化功能,可以把随时的变化的数据都在硬盘备份一份。防止数据丢失

同类型产品Memcache

memory cache 内存缓存

Redis与Memcache比较:

① Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash,bitmaps, hyperloglogs 等数据结构的存储。
② Redis支持数据的备份,即master-slave(主—从)模式的数据备份。
③ Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
④ Redis单个value的最大限制是1GB, Memcached只能保存1MB的数据

什么场合使用Redis

① [Sort Set]排行榜应用,取top n操作,例如sina微博热门话题
② [List]获得最新N个数据 或 某个分类的最新数据
③ [Set]sns(social network site)获得共同好友
④ [Set]防攻击系统(ip判断)等等
⑤ Pub/Sub构建实时消息系统,比如很多用Pub/Sub构建的实时聊天系统的例子

编译和安装Redis

进入下载目录

1
cd /usr/local

下载redis

1
wget http://download.redis.io/releases/redis-3.0.5.tar.gz

解压缩

1
tar -zxvf redis-3.0.5.tar.gz

进入安装目录

1
cd redis-3.0.5/src

查看cpu型号

1
uname -m

编译安装

1
make CFLAGS=”-march=i686”;

说明:make 后面一串代码: CFLAGS=”-march=i686” 是防止软件版本与Linux硬件不适配的。Linux有i386和i686这种区别;在redis软件与硬件不适配的情况下直接使用make命令编译,会报错误。

创建一个工作目录

1
mkdir /usr/local/redis

将编译安装后的三个文件复制到工作目录下

1
cp redis-cli redis-server ../redis.conf /usr/local/redis

最终结果是,redis目录下有了三个文件

1
2
3
redis-cli     // 客户端指令文件
redis-server // 服务指令文件
redis.conf // 配置文件

修改配置文件redis.conf,配置redis作为守护进程运行

1
2
vim redis.conf
daemonize yes

默认情况下redis不是作为守护进程运行的,如果想让它在后台运行,需要把配置文件里daemonize改成 yes。

启动redis服务

1
./redis-server &

如果修改过配置文件后

1
./redis-server redis.conf

杀掉rdis进程,然后再次打开redis服务

1
2
killall redis-server
./redis-server redis.conf

查看进程里面有没有redis服务,可以用pstree命令查看进程:

1
pstree

查看对应的服务进程

1
ps -A | grep redis

检测客户端检测连接是否正常

1
./redis-cli

src目录下相关文件

1
2
3
4
5
6
7
8
9
10
11
12
// 压力测试
redis-benchmark
// 检查redis持久化命令文件的完整性
redis-check-aof
// 检查redis持久化数据文件的完整性
redis-check-dump
// redis在linux上的客户端
redis-cli
// 做集群用的
redis-sentinel
// linux上的服务端
redis-server

编译安装PHPRedis

1
2
3
4
5
6
7
解压 phpredis.tar.gz
在解压目录执行 /usr/local/php/bin/phpize
安装 autoconf-2.6.2.tar.gz
配置编译phpredis
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
在php.ini配置文件中引入redis

keys键的操作

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
// 获取所有的key
keys *
// 测试指定的key是否存在
exists key
// 删除给定的key
del key1 key2 key3 ....keyN
// 返回给定key的value类型
type key
// 返回匹配指定模式的所有key
keys pattern
// 返回从当前数据库中随机选取的一个key
randomkey
// 改名字
rename oldkey newkey
// 返回当前数据库的key数量
dbsize
// 为key指定过期时间
expire key seconds
// 返回key的剩余过期秒数
tt1 key
// 选择数据库
select db-index
// 将key从当前数据库移动到指定数据库
move key db-index
// 删除当前数据库中所有key
flushdb
// 删除所有数据库中的所有key
flushall

string类型操作

string是redis最基本的类型,而且string类型是二进制安全的。

redis的string可以包含任何数据。包括jpg图片或者序列化的对象。

单个value值最大上限是1G字节。

如果只用string类型,redis就可以被看作加上持久化特性的memcached。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 设置key对应的值为 string 类型的value
set key value
// 一次设置多个key的值
mset key1 value1 ... keyN valueN
// 一次获取多个key的值
mget key1 key2 ... keyN
// 对key的值做加加操作,并返回新的值
incr key
// 减减操作
decr key
// 加指定值
incrby key integer
// 减指定值
decrby key integer
// 给指定key的字符串追加value
append key value
// 返回截取过的key的字符串值
substr key start end

list数据类型

list类型其实就是一个双向链表。

通过push,pop操作从链表的头部或者尾部添加删除元素。

这使得list既可以用作栈,也可以用作队列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 在key对应list的头部添加字符串元素
lpush key string
// 在尾部添加字符串元素
rpush key string
// 返回key对应list的长度,key不存在返回0
llen key
// 返回指定区间内的元素 下标从0开始
lrange key start end
// 截取list,保留指定区间内元素
ltrim key start end
// 设置list中指定下标的元素值
lset key index value
// 从key对应list中删除count个和value相同的元素,count为0的时候删除全部
lrem key count value
// 从list的头部删除元素,并返回删除元素
lpop key
// 从list的尾部删除元素,并返回删除元素
rpop key

sort set排序数据类型

redis的set是string类型的无序集合。

set元素最大可以包含(2的32次方-1)个元素。

关于set集合类型除了基本的添加删除操作,其他有用的操作还包含集合的取并集(union),交集(intersection),差集(difference)。

通过这些操作可以很容易的实现sns中的好友推荐功能。

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
// 添加元素到集合,元素在集合中存在则更新对应score
zadd key score member
// 删除指定元素 1表示成功 0表示元素不存在
zrem key member
// 按照incr幅度增加对应member的score值
zincrby key incr member
// 返回指定元素在集合中的排名(下标)
zrank key member
// 集合中的元素按score从大到小排序
zrevrank key start end
// 类似lrange操作从集合中去除指定区间的元素 正序 从小到大
zrange key start end
// 返回的结果按score逆序的 从大到小
zrevrange key start end
// 返回集合中的score在给定区间的元素
zrangebyscore key min max
// 返回集合中score在给定区间的数量
zcount key min max
// 返回集合中元素的个数
zcard key
// 返回给定元素对应的score
zscore key elemenr
// 删除集合中排名在给定区间的元素
zremrangebyrank key min max
// 删除集合中score在给定区间的元素
zremrangebyscore key min max

hash数据类型

hash数据类型存储的数据与mysql数据库中存储的一条记录极为相似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 设置hash field 为指定值,如果key不存在则创建
hset key field value
// 获取指定的 hash field
hget key field
// 获取全部指定的hash field
hmget key field1 ...fieldN
// 同时设置hash的多个field
hmset key field1 value1
// 将指定的hash field 加上给定值
hincrby key field integer
// 测试指定 field 是否存在
hexists key field
// 删除指定的 hash field
hdel key field
// 返回指定hash的field
hlen key
// 返回hash的所有field
hkeys key
// 返回hash的所有value
hvals key
// 返回hash的所有field和value
hgetall key

redis持久化

  • redis较比其他同类型产品有个最大的好处可以进行持久化操作。
  • 其会根据不同条件的触发,随时把当前内存存储的数据以文件形式保存在硬盘里边,这样服务器断电、或重启系统服务器,数据还会从硬盘里边恢复到内存里。

① snapshotting 快照方式持久化(默认文件名dump.rdb)

1
2
3
4
5
6
7
8
该方式持久化保存内存数据不能太频繁
该方式是一次性把全部redis的内存数据都保存在硬盘里边,如果数据非常多(例如10-20G大小)每备份一次消耗的时间非常多。
触发条件:(组合方式)
save 900 1 //900秒内如果超过1个key被修改,则发起快照保存
save 300 10 //300秒内超过一个key被修改,发起快照
save 60 10000 //60秒内超过10000个key被改变,发起快照
手动发起快照:
./redis-cli bgsave

1
2
3
snapshotting快照方式持久化的密度非常大,必须触发指定的条件才会执行该方式快照。
快照方式每次持久化都非常消耗时间,不适合频繁使用。
再者快照方式持久化密度大,服务器突然断电会出现数据丢失的情况。

② append-only-file 追加方式持久化(AOF)
AOF持久化又称为“增量”方式持久化。
可以使得快照 和 AOF结合对数据进行备份
① 快照在每月1号发起一次
②AOF是每秒都发起,是对快照方式的补充
AOF保存的数据是从当前时间点开始变化的数据
如果数据需要恢复,则从两个文件恢复数据:快照备份文件 + AOF备份文件

1
2
3
4
5
6
7
8
9
10
11
appendonly yes	启用 aof 持久化方式
appendfilename appendonly.aof 保存命令的文件
appendfsync always 每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec 每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
appendfsync no 完全依赖 os,性能最好,持久化没保证
save 同步保存数据到磁盘
bgsave 异步保存数据到磁盘
lastsave 返回上次成功保存到磁盘的unix时间戳
shutdown 同步保存到服务器并关闭redis服务器
bgrewriteaof 当日志文件过长时优化日志文件存储
./redis-cli -h 127.0.0.1 -p 6379 bgsave 手动发起快照

redis的主从配置

  • mysql有读写分离技术,有的mysql专门做数据写入(添加、update、删除)操作,有的mysql专门做数据读取操作。
  • 服务器如果负载较高,也需要做主从(分离)配置
    有的服务器安装apache+php
    有的服务器安装mysql
    有的服务器专门处理图片请求
    有的服务器专门处理音乐、视频请求。
  • redis如果负载较高也做主从配置
    有的服务器专门做数据写入操作
    有的服务器专门做数据读取操作
    主从复制的特点:
    1
    2
    3
    4
    5
    6
    master可以由多个slave
    除了多个slave连接到master外,slave也可以连接到其他slave,形成网状结构
    masterslave初次同步数据时不会阻塞,slavemaster初次同步数据同时会阻塞不能处理client请求
    可以让slave做读请求,master做写操作
    可以在master中注释掉配置文件中的save指令达到禁用持久化操作,然后只让slave做持久化
    save 10000000000 10000000000

主从服务器设置:

1
2
3
4
5
6
7
8
9
# vim /etc/redis.conf
daemonize yes
port 6379
requirepass 123456 #主服务器连接密码
# vim /etc/redis.conf
daemonize yes
port 6300
slaveof 192.168.1.100 6379
masterauth 123456 #从服务器连接密码

php操作redis

创建redis扩展文件:
① 下载phpredis扩展包
上传至linux指定目录(/home/wangxiong/rdtar)
② 进入phpredis源码目录并执行php的bin目录下的phpize工具

1
2
3
4
5
shell# cd /home/wangxiong/tar
shell# tar zxvf phpredis.tar.gz
shell# cd phpredis
shell# /usr/local/php/bin/phpize ????
以上这个指令必须在phpredis解压包目录/home/wangxiong/tar/phpredis(根据个人情况设置)执行

③ 安装autoconf-2.62.tar.gz

1
2
3
4
shell# cd /home/wagxiong/tar
shell# tar zxvf autoconf-2.62.tar.gz
shell# cd autoconf-2.62
shell# ./configure && make && make install

④ 配置并编译安装phpredis

1
2
shell#./configure --with-php-config=/usr/local/php/bin/php-config
shell# make && make install

⑤ 给php.ini设置redis扩展

1
2
3
shell# vi /usr/local/php/lib/php.ini
[redis]
extension=redis.so

⑥ 重启apache,查看php是否有引入redis扩展

1
shell# /usr/local/http2/bin/apachectl restart

⑦ php使用redis示例代码

1
2
3
4
5
6
7
<?php
$redis = new Redis();
$redis->connect('localhost','6379');
$redis->set('address','beijing');
$resid->lpush('newgoods','htc');
$redis->lpush('newgoods','xiaomi');
$redis->mset(array('animal1'=>'dog','animal2'=>'cat','animal3'=>'pig'));