NoSQL概述、部署Redis服务、Redis数据类型、Redis其他操作命令、部署支持PHP和Redis的Nginx服务器

NoSQL概述

数据库类型

RDBMS

  • 关系数据库管理系统:Relational Database Management System
  • 按照预先设置的组织结构,将数据存储在物理介质上
  • 数据之间可以做关联操作
  • 主流的RDBMS软件
    • MySQL
    • MariaDB
    • Oracle
    • DB2
    • SQL Server
    • PostgreSQL

NoSQL:Not Only SQL

  • 意为"不仅仅是SQL"
  • 泛指非关系型数据库
  • 不需要预先定义数据存储结构
  • 每条记录可以有不同的数据类型和字段个数
  • 在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL来存储。比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。这样可以避免经常对MySQL进行表结构调整,增加字段带来的性能问题。
  • 这种架构的缺点就是数据直接存储在NoSQL中,不能做关系数据库的复杂查询,如果由于需求变更,需要进行某些查询,可能无法满足,所以采用这种架构的时候需要确认未来是否会进行复杂关系查询以及如何应对。
  • 主流软件
    • Redis
    • Memcached
    • MongoDB
    • CouchDB
    • Neo4j
    • FlockDB

部署Redis服务

在redis1(192.168.1.11)上部署redis

  • 安装编译器
[root@redis1 ~]# yum install -y gcc
  • 编译安装redis
[root@redis1 ~]# tar xf redis-4.0.8.tar.gz
[root@redis1 ~]# cd redis-4.0.8

# 修改安装目录为/usr/local/redis
[root@redis1 redis-4.0.8]# vim +27 src/Makefile
PREFIX?=/usr/local/redis

# 编译安装
[root@redis1 redis-4.0.8]# make && make install

# 将redis命令目录添加至PATH环境变量
[root@redis1 redis-4.0.8]# vim /etc/bashrc   # 尾部追加
export PATH=$PATH:/usr/local/redis/bin
[root@redis1 redis-4.0.8]# source /etc/bashrc

# 初始化redis服务
[root@redis1 redis-4.0.8]# ./utils/install_server.sh  # 全部问题直接回车采用默认值
Welcome to the redis service installer
This script will help you easily set up a running redis server

Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/redis/bin/redis-server]
Selected config:
Port           : 6379
Config file    : /etc/redis/6379.conf
Log file       : /var/log/redis_6379.log
Data dir       : /var/lib/redis/6379
Executable     : /usr/local/redis/bin/redis-server
Cli Executable : /usr/local/redis/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
  • 验证服务
# 查看服务状态
[root@redis1 ~]# /etc/init.d/redis_6379 status
Redis is running (10023)
# 也可以使用以下方式查看服务状态
[root@redis1 ~]# service redis_6379 status
Redis is running (10023)

[root@redis1 ~]# ss -tlnp | grep :6379
LISTEN     0      128    127.0.0.1:6379                     *:*                   users:(("redis-server",pid=10023,fd=6))

# 关闭服务
[root@redis1 ~]# service redis_6379 stop
Stopping ...
Redis stopped
# 也可以使用以下方式关闭服务
[root@redis1 ~]# /etc/init.d/redis_6379 stop

# 启动服务
[root@redis1 ~]# service redis_6379 start
Starting Redis server...
# 也可以使用以下方式启动服务
[root@redis1 ~]# /etc/init.d/redis_6379 start

# 重启服务
[root@redis1 ~]# service redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
# 也可以使用以下方式重启服务
[root@redis1 ~]# /etc/init.d/redis_6379 restart

# 连接redis
[root@redis1 ~]# redis-cli
127.0.0.1:6379> ping  # 测试服务,正常返回PONG
PONG
127.0.0.1:6379> exit

Redis数据类型

字符串

  • 字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据
  • 可以用其存储用户的邮箱、JSON 化的对象甚至是一张图片
  • 一个字符串类型键允许存储的数据的最大容量是512 MB
  • 字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是组织字符串的形式不同

字符串操作命令

  • 赋值命令
# 赋值
SET key value

# 取值
GET key
  • 赋值命令示例
127.0.0.1:6379> SET username tom
OK

127.0.0.1:6379> GET username
"tom"

127.0.0.1:6379> GET password    # 当键不存在时会返回空结果。
(nil)
  • 递增数字:字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,Redis 提供了一个实用的命令 INCR,其作用是让当前键值递增,并返回递增后的值。
# 当要操作的键不存在时会默认键值为0,所以第一次递增后的结果是1。
127.0.0.1:6379> INCR num
(integer) 1

127.0.0.1:6379> INCR num
(integer) 2

127.0.0.1:6379> GET num
"2"
  • 当键值不是整数时Redis会提示错误
127.0.0.1:6379> SET foo bar
OK

127.0.0.1:6379> INCR foo
(error) ERR value is not an integer or out of range
  • 增加指定的整数
127.0.0.1:6379> INCRBY num 2
(integer) 4

127.0.0.1:6379> INCRBY num 2
(integer) 6
  • 递减数字
127.0.0.1:6379> DECR num
(integer) 5

127.0.0.1:6379> DECRBY num 2
(integer) 3
  • 向尾部追加值
127.0.0.1:6379> SET hi Hello
OK

127.0.0.1:6379> APPEND hi " World"   # 因为字符串包含空格,需要使用引号
(integer) 11        # 返回值为hi的总长度

127.0.0.1:6379> GET hi
"Hello World"
  • 获取字符串长度
127.0.0.1:6379> STRLEN hi
(integer) 11
  • 中文字符返回字节数
127.0.0.1:6379> SET name 张三
OK

127.0.0.1:6379> STRLEN name
(integer) 6   # UTF-8编码的中文,由于“张”和“三”两个字的UTF-8编码的长度都是3,所以此例中会返回6。
  • 同时获得/设置多个键值
127.0.0.1:6379> MSET username tom password tedu.cn
OK

127.0.0.1:6379> MGET username password
1) "tom"
2) "tedu.cn"
  • 判断字段是否存在
127.0.0.1:6379> EXISTS num
(integer) 1

127.0.0.1:6379> EXISTS number
(integer) 0
  • 字段不存在时赋值
127.0.0.1:6379> SETNX number 100
(integer) 1

127.0.0.1:6379> GET number
"100"
  • 查看所有的key
127.0.0.1:6379> KEYS *
  • 删除字段
127.0.0.1:6379> DEL number
(integer) 1

127.0.0.1:6379> DEL number
(integer) 0
  • 查看键的类型
127.0.0.1:6379> TYPE name
string

字符串实践

  • Redis 对于键的命名并没有强制的要求,但比较好的实践是用“对象类型:对象ID:对象属性”来命名一个键,如使用键【user:1:friends】来存储ID为1的用户的好友列表。
  • 例:如果你正在编写一个博客网站,博客的一个常见的功能是统计文章的访问量,我们可以为每篇文章使用一个名为【post:文章ID:page.view】的键来记录文章的访问量,每次访问文章的时候使用INCR命令使相应的键值递增。
# 有用户访问文章ID号为42的博文,则将其访问计数加1
127.0.0.1:6379> INCR post:42:page.view
(integer) 1

127.0.0.1:6379> GET post:42:page.view
"1"

127.0.0.1:6379> INCR post:42:page.view
(integer) 2

127.0.0.1:6379> GET post:42:page.view
"2"

散列类型

  • 散列类型(hash)的键值也是一种字典结构,其存储了字段(field)和字段值的映射
  • 字段值只能是字符串
  • 散列类型适合存储对象。使用对象类别和 ID 构成键名,使用字段表示对象的属性,而字段值则存储属性值

散列类型操作命令

  • 赋值与取值
# 设置单个字段
127.0.0.1:6379> HSET user1 name bob
(integer) 1

127.0.0.1:6379> HSET user1 gender male
(integer) 1

127.0.0.1:6379> HGET user1 name
"bob"

127.0.0.1:6379> HGET user1 gender
"male"


# 设置多个字段
127.0.0.1:6379> HMSET user1 email bob@tedu.cn phone 13412345678
OK
127.0.0.1:6379> HMGET user1 email phone
1) "bob@tedu.cn"
2) "13412345678"

# 获取所有字段
127.0.0.1:6379> HGETALL user1
1) "name"
2) "bob"
3) "gender"
4) "male"
5) "email"
6) "bob@tedu.cn"
7) "phone"
8) "13412345678"
  • 判断
# 判断字段是否存在
127.0.0.1:6379> HEXISTS user1 address
(integer) 0

127.0.0.1:6379> HEXISTS user1 name
(integer) 1

# 当字段不存在时赋值
127.0.0.1:6379> HSETNX user1 address beijing
(integer) 1

127.0.0.1:6379> HSETNX user1 address shanghai
(integer) 0
  • 数字递增
127.0.0.1:6379> HINCRBY user1 age 20
(integer) 20

127.0.0.1:6379> HINCRBY user1 age 1
(integer) 21
  • 删除字段
127.0.0.1:6379> HDEL user1 age
(integer) 1
  • 只获取字段名
127.0.0.1:6379> HKEYS user1
1) "name"
2) "gender"
3) "email"
4) "phone"
5) "address"
  • 只获取值
127.0.0.1:6379> HVALS user1
1) "bob"
2) "male"
3) "bob@tedu.cn"
4) "13412345678"
5) "beijing"
  • 获得字段数量
127.0.0.1:6379> HLEN user1
(integer) 5

散列类型实践

  • 例:将文章ID号为10的文章以散列类型存储在Redis中
127.0.0.1:6379> HSET post:10 title 例解Python
(integer) 1

127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"

127.0.0.1:6379> HSET post:10 author ZhangZhiGang
(integer) 1


127.0.0.1:6379> HMSET post:10 date 2021-05-01 summary 'Python Programming'
OK

127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"
3) "author"
4) "ZhangZhiGang"
5) "date"
6) "2021-05-01"
7) "summary"
8) "Python Programming"

列表类型

  • 列表类型(list)可以存储一个有序的字符串列表

  • 常用的操作是向列表两端添加元素,或者获得列表的某一个片段

  • 列表类型内部是使用双向链表(double linked list)实现的,获取越接近两端的元素速度就越快

  • 使用链表的代价是通过索引访问元素比较慢

  • 这种特性使列表类型能非常快速地完成关系数据库难以应付的场景:如社交网站的新鲜事,我们关心的只是最新的内容,使用列表类型存储,即使新鲜事的总数达到几千万个,获取其中最新的100条数据也是极快的

列表类型操作命令

  • LPUSH命令用来向列表左边增加元素,返回值表示增加元素后列表的长度
127.0.0.1:6379> LPUSH numbers 1
(integer) 1

127.0.0.1:6379> LPUSH numbers 2 3
(integer) 3
  • 取出列表所有元素
127.0.0.1:6379> LRANGE numbers 0 -1  # 起始下标为0,结束下标为-1
1) "3"
2) "2"
3) "1"
  • RPUSH命令用来向列表右边增加元素,返回值表示增加元素后列表的长度
127.0.0.1:6379> RPUSH numbers 0 -1
(integer) 5

127.0.0.1:6379> LRANGE numbers 0 -1
1) "3"
2) "2"
3) "1"
4) "0"
5) "-1"
  • 从列表两端弹出元素
127.0.0.1:6379> LPOP numbers
"3"
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
4) "-1"

127.0.0.1:6379> RPOP numbers
"-1"

127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
  • 获取列表中元素的个数
127.0.0.1:6379> LLEN numbers
(integer) 3
  • 删除列表中指定的值
# 语法
LREM key count value
#LREM命令会删除列表中前count个值为value的元素,返回值是实际删除的元素个数。根据count值的不同,LREM命令的执行方式会略有差异。
#(1)当 count > 0时 LREM 命令会从列表左边开始删除前 count 个值为 value的元素。
#(2)当 count < 0时 LREM 命令会从列表右边开始删除前 count 个值为 value 的元素。
#(3)当 count = 0是 LREM命令会删除所有值为 value的元素。

127.0.0.1:6379> LPUSH numbers 0 1 2 0 1 2 0 1 2
(integer) 12

127.0.0.1:6379> RPUSH numbers 2 1 0 2 1 0 2 1 0
(integer) 21

127.0.0.1:6379> LRANGE numbers 0 -1
 1) "2"
 2) "1"
 3) "0"
 4) "2"
 5) "1"
 6) "0"
 7) "2"
 8) "1"
 9) "0"
10) "2"
11) "1"
12) "0"
13) "2"
14) "1"
15) "0"
16) "2"
17) "1"
18) "0"
19) "2"
20) "1"
21) "0"

# 
127.0.0.1:6379> LREM numbers 2 1   # 从左侧开始删除2个1
(integer) 2

127.0.0.1:6379> LRANGE numbers 0 -1
 1) "2"
 2) "0"
 3) "2"
 4) "0"
 5) "2"
 6) "1"
 7) "0"
 8) "2"
 9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "0"
17) "2"
18) "1"
19) "0"

# 从右侧开始删除2个0
127.0.0.1:6379> LREM numbers -2 0
(integer) 2

127.0.0.1:6379> LRANGE numbers 0 -1
 1) "2"
 2) "0"
 3) "2"
 4) "0"
 5) "2"
 6) "1"
 7) "0"
 8) "2"
 9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "2"
17) "1"

# 删除所有的0
127.0.0.1:6379> LREM numbers 0 0
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
 1) "2"
 2) "2"
 3) "2"
 4) "1"
 5) "2"
 6) "1"
 7) "2"
 8) "1"
 9) "2"
10) "1"
11) "2"
12) "1"
  • 获得/设置指定索引的元素值
# 获取numbers列表中下标为0的值
127.0.0.1:6379> LINDEX numbers 0
"2"

# 设置下标为1的值为10
127.0.0.1:6379> LSET numbers 1 10
OK

127.0.0.1:6379> LRANGE numbers 0 -1
 1) "2"
 2) "10"
 3) "2"
 4) "1"
 5) "2"
 6) "1"
 7) "2"
 8) "1"
 9) "2"
10) "1"
11) "2"
12) "1"
  • 删除指定范围之外的所有元素
127.0.0.1:6379> LTRIM numbers 0 2
OK

127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "10"
3) "2"
  • 插入元素
# 在2的前面插入20
127.0.0.1:6379> LINSERT numbers BEFORE 2 20
(integer) 4

127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "10"
4) "2"

# 在2的后面插入30
127.0.0.1:6379> LINSERT numbers AFTER 2 30
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "30"
4) "10"
5) "2"

列表类型实践

  • 例:记录最新的10篇博文
127.0.0.1:6379> LPUSH posts:list 11 12 13
(integer) 3

127.0.0.1:6379> LRANGE posts:list 0 -1
1) "13"
2) "12"
3) "11"

集合类型

  • 集合中的每个元素都是不同的,且没有顺序

  • 增加/删除元素

127.0.0.1:6379> SADD letters a b c
(integer) 3

127.0.0.1:6379> SADD letters b c d
(integer) 1

127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
3) "a"
4) "c"

127.0.0.1:6379> SREM letters a c
(integer) 2

127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
  • 判断元素是否在集合中
127.0.0.1:6379> SISMEMBER letters a
(integer) 0

127.0.0.1:6379> SISMEMBER letters b
(integer) 1
  • 集合运算
127.0.0.1:6379> SADD s1 a b c
(integer) 3

127.0.0.1:6379> SADD s2 b c d
(integer) 3

127.0.0.1:6379> SINTER s1 s2
1) "b"
2) "c"

127.0.0.1:6379> SUNION s1 s2
1) "a"
2) "c"
3) "b"
4) "d"

127.0.0.1:6379> SDIFF s1 s2
1) "a"
  • 获得集合中元素个数
127.0.0.1:6379> SCARD letters
(integer) 2
  • 随机获得集合中的元素
# 在集合s1中随机取出两个不同元素。
127.0.0.1:6379> SRANDMEMBER s1 2
1) "b"
2) "c"

# 在集合s1中随机取出两个有可能相同元素。
127.0.0.1:6379> SRANDMEMBER s1 -2
1) "c"
2) "c"

127.0.0.1:6379> SRANDMEMBER s1 -2
1) "a"
2) "b"
  • 集合中随机弹出一个元素
127.0.0.1:6379> SPOP s1
"a"

127.0.0.1:6379> SMEMBERS s1
1) "b"
2) "c"

集合实践

  • 例:为文章号为10的博客文章添加标签
127.0.0.1:6379> SADD post:10:tags python redis nginx
(integer) 3

127.0.0.1:6379> SMEMBERS post:10:tags
1) "python"
2) "nginx"
3) "redis"

有序集合类型

  • 在集合类型的基础上有序集合类型为集合中的每个元素都关联了一个分数

  • 这使得我们不仅可以完成插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最高(或最低)的前N个元素、获得指定分数范围内的元素等与分数有关的操作

  • 虽然集合中每个元素都是不同的,但是它们的分数却可以相同。

  • 有序集合类型在某些方面和列表类型有些相似

    • 二者都是有序的
    • 二者都可以获得某一范围的元素
  • 有序集合类型和列表也有着很大的区别,这使得它们的应用场景也是不同的

    • 列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元素的应用
    • 有序集合类型是使用散列表和跳跃表(Skip list)实现的,所以即使读取位于中间部分的数据速度也很快
    • 列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素的分数)
    • 有序集合要比列表类型更耗费内存

有序集合类型操作

  • ZADD 命令用来向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数
127.0.0.1:6379> ZADD scores 88 tom 90 jerry 75 bob 92 alice
(integer) 4

127.0.0.1:6379> ZRANGE scores 0 -1
1) "bob"
2) "tom"
3) "jerry"
4) "alice"

127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "tom"
4) "88"
5) "jerry"
6) "90"
7) "alice"
8) "92"

127.0.0.1:6379> ZADD scores 85 jerry
(integer) 0

127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "jerry"
4) "85"
5) "tom"
6) "88"
7) "alice"
8) "92"
  • 获得元素的分数
127.0.0.1:6379> ZSCORE scores tom
"88"
  • 获得指定分数范围的元素
127.0.0.1:6379> ZRANGEBYSCORE scores 80 90 WITHSCORES
1) "jerry"
2) "85"
3) "tom"
4) "88"
  • 增加某个元素的分数
127.0.0.1:6379> ZINCRBY scores 3 bob
"78"

127.0.0.1:6379> ZSCORE scores bob
"78"
  • 获得集合中元素的数量
127.0.0.1:6379> ZCARD scores
(integer) 4
  • 获得指定分数范围内的元素个数
127.0.0.1:6379> ZCOUNT scores 80 90
(integer) 2
  • 删除元素
127.0.0.1:6379> ZREM scores bob
(integer) 1
  • 获得元素的排名
127.0.0.1:6379> ZRANK scores tom   # 获取tom的排名
(integer) 1   # 升序排列,从0开始计数

127.0.0.1:6379> ZREVRANK scores alice   # 获取alice的排名
(integer) 0   # 降序排列,从0开始计数

有序集合类型实践

  • 例:将博客文章按照点击量排序
127.0.0.1:6379> ZADD posts:page.view 0 post:10:page.view
(integer) 1

127.0.0.1:6379> ZINCRBY posts:page.view 1 post:10:page.view
"1"

127.0.0.1:6379> ZRANGE posts:page.view 0 -1 WITHSCORES
1) "post:10:page.view"
2) "1"

Redis其他操作命令

数据操作命令

  • 查看key过期时间
127.0.0.1:6379> TTL name
(integer) -1    # -1 表示永不过期

# 创建key的同时,设置它的过期时间。key是user1:login,value是235124,超时时间60秒
127.0.0.1:6379> SET user1:login 235124 ex 60
OK
  • 设置key的过期时间(秒)
127.0.0.1:6379> EXPIRE password 20
(integer) 1

127.0.0.1:6379> TTL password
(integer) 15

127.0.0.1:6379> TTL password
(integer) -2   # -2表示已过期
  • 查看key是否存在
127.0.0.1:6379> EXISTS password
(integer) 0
  • 存盘
127.0.0.1:6379> SAVE
OK

数据库操作命令

  • 默认Redis有16个库,将name移动到1号库
127.0.0.1:6379> MOVE name 1
(integer) 1
  • 选择库
127.0.0.1:6379> SELECT 1
OK

127.0.0.1:6379[1]> KEYS *
1) "name"
  • 清除库
# 清除当前库
127.0.0.1:6379[1]> FLUSHDB
OK

127.0.0.1:6379[1]> KEYS *
(empty list or set)

# 清除所有库
127.0.0.1:6379[1]> SELECT 0
OK

127.0.0.1:6379> KEYS *
 1) "numbers"
 2) "2"
 3) "posts:list"
 4) "letters"
 5) "posts:page.view"
 6) "scores"
 7) "post:10:tags"
 8) "foo"
 9) "s1"
10) "s2"
11) "num"
12) "post:10"
13) "user1"
14) "username"
15) "hi"
16) "post:42:page.view"

127.0.0.1:6379> SELECT 1
OK

127.0.0.1:6379[1]> FLUSHALL
OK

127.0.0.1:6379[1]> SELECT 1
OK

127.0.0.1:6379[1]> KEYS *
(empty list or set)
  • 关闭Redis
127.0.0.1:6379> SHUTDOWN
not connected> exit

修改Redis服务运行参数

常用参数

  • 监听地址:默认运行在127.0.0.1上
  • 监听端口:默认监听6379端口(不用修改)
  • 密码
[root@redis1 ~]# vim /etc/redis/6379.conf 
protected-mode no        # 关闭保护模式,以允许不指定服务绑定在哪个地址
# bind 127.0.0.1         # 注释此行,运行在0.0.0.0上
port 6379                # 端口号
requirepass tedu.cn      # 密码
  • 修改启动脚本
[root@redis1 ~]# vim +43 /etc/init.d/redis_6379 
... ...
            $CLIEXEC -p $REDISPORT -a tedu.cn shutdown
... ...
  • 启动服务并测试
[root@redis1 ~]# service redis_6379 start
Starting Redis server...

[root@redis1 ~]# redis-cli -h 192.168.1.11 -p 6379 -a tedu.cn
192.168.1.11:6379> PING
PONG

附:python操作redis

# 安装redis模块
[root@zzgrhel8 ~]# pip3 install redis

# 操作
[root@zzgrhel8 ~]# python3
>>> import redis
>>> help(redis.Redis)
>>> r = redis.Redis(host='192.168.1.11', db=0, password='tedu.cn')
# 操作字符串类型数据
>>> r.set('name', 'tom')

# 更多操作参见:https://www.cnblogs.com/melonjiang/p/5342505.html

部署支持php和Redis的Nginx服务器

安装并配置Nginx服务器

  • 在nginx1(192.168.1.10)上安装nginx
# 安装编译器
[root@nginx1 ~]# yum install -y gcc pcre-devel zlib-devel

# 编译安装nginx
[root@nginx1 ~]# tar xf nginx-1.12.2.tar.gz 
[root@nginx1 ~]# cd nginx-1.12.2
[root@nginx1 nginx-1.12.2]# ./configure 
[root@nginx1 nginx-1.12.2]# make && make install
  • 安装php-fpm
[root@nginx1 ~]# yum install -y php-fpm

[root@nginx1 ~]# systemctl start php-fpm

[root@nginx1 ~]# ss -tlnp | grep :9000
LISTEN     0      128    127.0.0.1:9000                     *:*                   users:(("php-fpm",pid=11310,fd=0),("php-fpm",pid=11309,fd=0),("php-fpm",pid=11308,fd=0),("php-fpm",pid=11307,fd=0),("php-fpm",pid=11306,fd=0),("php-fpm",pid=11305,fd=6))
  • 修改配置文件
[root@nginx1 ~]# vim +65 /usr/local/nginx/conf/nginx.conf
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi.conf;
        }
  • 启动nginx服务
[root@nginx1 ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

[root@nginx1 ~]# /usr/local/nginx/sbin/nginx

[root@nginx1 ~]# ss -tlnp | grep :80
LISTEN     0      128          *:80                       *:*                   users:(("nginx",pid=11376,fd=6),("nginx",pid=11375,fd=6))
  • 测试
[root@nginx1 ~]# vim /usr/local/nginx/html/test.php
<?php
    echo "Hello World!\n";
    phpinfo();
?>

[root@nginx1 ~]# curl http://127.0.0.1/test.php
Hello World!
... ...

配置PHP支持Redis

  • 安装php扩展
[root@nginx1 ~]# yum install -y php-devel automake autoconf
  • 安装php-redis
[root@nginx1 ~]# tar xf redis-cluster-4.3.0.tgz
[root@nginx1 ~]# cd redis-4.3.0/
[root@nginx1 redis-4.3.0]# phpize 
[root@nginx1 redis-4.3.0]# ./configure --with-php-config=/usr/bin/php-config 
[root@nginx1 redis-4.3.0]# make && make install

[root@nginx1 redis-4.3.0]# ls /usr/lib64/php/modules/redis.so 
/usr/lib64/php/modules/redis.so
  • 修改php配置文件并重启服务
[root@nginx1 redis-4.3.0]# vim /etc/php.ini   # 在730行下添加
extension_dir = "/usr/lib64/php/modules"
extension = "redis.so"

[root@nginx1 ~]# systemctl restart php-fpm
  • 测试
# 创建脚本,写入redis数据库
[root@nginx1 ~]# vim /usr/local/nginx/html/set_redis.php
<?php
    $redis = new redis();
    $redis->connect("192.168.1.11", "6379");
    $redis->auth("tedu.cn");
    $redis->set("username", "tom");
?>

# 创建脚本,读取redis数据
[root@nginx1 ~]# vim /usr/local/nginx/html/get_redis.php
<?php
    $redis = new redis();
    $redis->connect("192.168.1.11", "6379");
    $redis->auth("tedu.cn");
    echo $redis->get("username");
?>

# 访问测试页面
[root@nginx1 ~]# curl http://127.0.0.1/set_redis.php
[root@nginx1 ~]# curl http://127.0.0.1/get_redis.php
tom

# 在redis数据库上查看
[root@redis1 ~]# redis-cli -a tedu.cn
127.0.0.1:6379> KEYS *
1) "username"
127.0.0.1:6379> GET username
"tom"

附加练习:参见【tedu_nsd/software/php_redis_mysql_bbs/】

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容