重要内容:
NoSQL概述(RDBMS、NoSQL)、部署Redis服务、Redis数据类型(字符串、散列类型、列表类型、集合类型、有序集合类型)、Redis别的操作命令、修改Redis服务运行参数、部署支持PHP和Redis的Nginx服务器
一、NoSQL概述
NoSQL(Not Only SQL)是一类非关系型数据库管理系统(DBMS),它们不使用传统的基于表格的关系模型,而是采用各种不同的数据模型来存储和检索数据。NoSQL 数据库的设计目标是为了办理传统关系型数据库在某些场景下的局限性,特别是在处置惩罚大规模数据、高并发访问和分布式系统时。
1、数据类型
① RDBMS
- 关系数据库管理系统:Relational Database Management System
- 按照预先设置的构造结构,将数据存储在物理介质上,数据之间可以做关联操作
- 主流的RDBMS软件:MySQL、MariaDB、Oracle、DB2、SQL Server、PostgreSQL
② NoSQL
- 泛指非关系型数据库:Not Only SQL(意为"不仅仅是SQL")
- 不需要预先定义数据存储结构,每条记录可以有不同的数据类型和字段个数
- 在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL来存储。比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。这样可以避免经常对MySQL进行表结构调解,增长字段带来的性能题目。
- 这种架构的缺点就是数据直接存储在NoSQL中,不能做关系数据库的复杂查询,假如由于需求变动,需要进行某些查询,可能无法满意,以是采用这种架构的时候需要确认将来是否会进行复杂关系查询以及怎样应对。
- 主流NoSQL软件:Redis、Memcached、MongoDB、CouchDB、Neo4j、FlockDB
2、NoSQL的重要特点:
NoSQL 数据库不使用 SQL 作为查询语言,而是使用其他查询语言或 API。
数据模型通常是非关系型的,如键值对、文档、列族、图等。
NoSQL 数据库通常设计为分布式系统,能够程度扩展,支持大规模数据存储和高并发访问。
支持数据分片(Sharding)和复制(Replication),进步系统的可用性和性能。
NoSQL 数据库通常具有动态模式(Schema),允许在运行时添加或修改数据结构,而不需要停机或重新设计数据库。
适合处置惩罚半结构化或非结构化数据。
由于去除了复杂的关系模型和事务处置惩罚,NoSQL 数据库通常具有更高的读写性能。
适合处置惩罚实时数据分析和高吞吐量的应用场景。
NoSQL 数据库通常设计为高可用性,支持主动故障转移和数据冗余。
适合需要持续在线服务的应用场景。
3、常见 NoSQL 数据库类型:
键值存储(Key-Value Stores):
文档存储(Document Stores):
- 数据模型:文档(通常是 JSON 或 BSON 格式)。
- 示例:MongoDB、CouchDB。
列族存储(Column Family Stores):
- 数据模型:列族(Column Families)。
- 示例:Apache Cassandra、HBase。
图数据库(Graph Databases):
- 数据模型:图结构(节点、边、属性)。
- 示例:Neo4j、OrientDB。
二、Redis介绍
Redis(Remote Dictionary Server)是一个开源的、高性能的键值存储系统,通常被称为数据结构服务器。它支持多种数据结构,如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。Redis 的设计目标是提供极高的性能和机动性,适用于多种应用场景,如缓存、消息队列、实时分析等。
官方网站:www.redis.cn/
重要特点:
高性能:
- Redis 是内存数据库,数据存储在内存中,因此读写速度非常快。
- 支持长期化(Persistence),可以将数据定期生存到磁盘,防止数据丢失。
数据结构丰富:
- 支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。
- 每种数据结构都有丰富的操作命令,如增编削查、排序、聚合等。
原子操作:
- Redis 的全部操作都是原子的,适合处置惩罚并发访问。
- 支持事务(Transaction),可以将多个命令打包成一个事务实行。
高可用性:
- 支持主从复制(Master-Slave Replication),进步系统的可用性和读写性能。
- 支持哨兵(Sentinel)机制,主动监控和管理 Redis 集群,实现故障转移。
分布式:
- 支持集群(Cluster)模式,可以将数据分布到多个节点,实现程度扩展。
- 支持分片(Sharding),可以将数据分散到不同的节点,进步系统的吞吐量。
机动性:
- 支持多种编程语言的客户端库,如 Python、Java、Node.js 等。
- 支持多种长期化方式,如 RDB(快照)和 AOF(日记)。
应用场景:
- 作为缓存层,存储频繁访问的数据,淘汰数据库的负载。适合处置惩罚高并发的读写请求,如 Web 应用的会话管理、页面缓存等。
- 作为轻量级的消息队列,支持发布/订阅(Pub/Sub)模式。适合处置惩罚实时消息传递,如聊天系统、实时关照等。
- 作为实时数据存储和分析平台,支持高效的聚合操作。适合处置惩罚实时统计、排行榜、计数器等。
- 作为会话存储,存储用户会话数据,支持分布式会话管理。适合处置惩罚分布式应用的会话管理,如 Web 应用、移动应用等。
- 作为分布式锁服务,支持高效的锁机制,防止并发辩论。适合处置惩罚分布式系统的并发控制,如分布式任务调度、资源管理等。
1、部署Redis服务
搭建Redis服务的三个重要步调:安装gcc编译器、编译安装、添加PATH情况变量、初始化启动服务
- 源码包目次:redis-4.0.8/
- 实行程序路径:/usr/local/redis/bin
- 初始化设置脚本:redis-4.0.8/utils/install_server.sh
- 服务启动脚本:/etc/init.d/redis_6379
- 数据库数据目次:/var/lib/redis/6379/
步调1:部署redis服务(参考:/linux-soft/4/redis-4.0.8.tar.gz)
- wget http://download.redis.io/releases/redis-4.0.8.tar.gz //没有安装包可联网下载
复制代码 1)安装gcc编译器
- [root@redis ~]# yum -y install gcc
复制代码 2)解压redis-4.0.8.tar.gz压缩包
- [root@redis ~]# tar -xf redis-4.0.8.tar.gz
- [root@redis ~]# cd redis-4.0.8/
- [root@redis redis-4.0.8]# ls
复制代码
3)修改安装目次为/usr/local/redis/
- [root@redis redis-4.0.8]# vim +27 src/Makefile
- PREFIX?=/usr/local/redis
- …
复制代码 4)编译安装(解压后,已设置好Makefile,无需configure,直接make编译调用gcc)
- [root@redis redis-4.0.8]# make && make install
复制代码 5)将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 //或者退出重新打开终端
复制代码 6)初始化redis服务(直接回车采用默认值)
切换到源码目次下的utils,运行初始化设置脚本install_server.sh
- [root@redis 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] //指定端口,Redis服务默认端口为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 //端口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!
复制代码 补充:初始化设置完成后,默认运行Redis服务;
常见报错: 未初始化redis或未启动服务,使用redis-cli提示服务拒绝访问
- [root@redis1 ~]# redis-cli
- Could not connect to Redis at 127.0.0.1:6379: Connection refused
- Could not connect to Redis at 127.0.0.1:6379: Connection refused
- not connected> exit
复制代码 7)验证Redis服务
① 检察服务状态:
# 使用/etc/init.d/redis_6379路径方式检察服务状态
- [root@redis ~]# /etc/init.d/redis_6379 status
- Redis is running (5030)
复制代码 # 使用service方式检察服务状态
- [root@redis ~]# service redis_6379 status //以前版本没有systemctl,用的就是service
- Redis is running (5030)
复制代码 # 检察服务端口状态信息
- [root@redis ~]# ss -nlptu | grep :6379
- tcp LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",pid=5030,fd=6))
复制代码 ② 关闭服务:
# 使用/etc/init.d/redis_6379路径方式关闭服务
- [root@redis ~]# service redis_6379 stop
- Stopping ...
- Redis stopped
复制代码 # 使用service方式关闭服务
- [root@redis ~]# /etc/init.d/redis_6379 stop
- Stopping ...
- Redis stopped
复制代码 ③ 开启服务:
# 使用/etc/init.d/redis_6379路径方式开启服务
- [root@redis ~]# /etc/init.d/redis_6379 start
- Starting Redis server...
复制代码 # 使用service方式开启服务
- [root@redis ~]# service redis_6379 start
- Starting Redis server...
复制代码 ④ 重启服务:
# 使用/etc/init.d/redis_6379路径方式重启服务
- [root@redis ~]# /etc/init.d/redis_6379 restart
- Stopping ...
- Redis stopped
- Starting Redis server...
复制代码 # 使用service方式重启服务
- [root@redis ~]# service redis_6379 restart
- Stopping ...
- Redis stopped
- Starting Redis server...
复制代码 ⑤ 连接Redis服务:
- [root@redis ~]# redis-cli
- 127.0.0.1:6379> ping //测试服务,正常返回PONG
- PONG
- 127.0.0.1:6379> exit
复制代码
2、Redis数据类型
Redis数据类型包罗:字符型、列表型、哈希型、集合型、有序集合型;
1. 字符型(String)
特点:最根本的数据类型,存储字符串、整数或浮点数。支持原子操作,如增减操作(INCR、DECR)。
SET key value:设置键值对。
GET key:获取键对应的值。
INCR key:将键对应的值加 1。
DECR key:将键对应的值减 1。
APPEND key value:将值追加到键对应的字符串末尾。
2. 列表型(List)
特点:存储有序的字符串列表,支持从两端插入和删除元素。适合实现队列、栈等数据结构。
LPUSH key value:将值插入到列表的头部。
RPUSH key value:将值插入到列表的尾部。
LPOP key:移除并返回列表头部的元素。
RPOP key:移除并返回列表尾部的元素。
LRANGE key start stop:获取列表中指定范围的元素。
3. 哈希型(Hash)
特点:存储字段和值的映射关系,适合存储对象。每个哈希可以存储多个字段-值对。
HSET key field value:设置哈希表中字段的值。
HGET key field:获取哈希表中字段的值。
HGETALL key:获取哈希表中全部字段和值。
HDEL key field:删除哈希表中的字段。
HINCRBY key field increment:将哈希表中字段的值增长指定的整数。
4. 集合型(Set)
特点:存储无序的字符串集合,不允许重复元素。支持集合运算,如并集、交集、差集。
SADD key member:向集合中添加元素。
SREM key member:从集合中移除元素。
SMEMBERS key:获取集合中的全部元素。
SISMEMBER key member:判定元素是否在集合中。
SUNION key1 key2:返回两个集合的并集。
5. 有序集合型(Sorted Set)
特点:存储有序的字符串集合,每个元素关联一个分数(score)。元素按分数从小到大排序,支持范围查询。
ZADD key score member:向有序集合中添加元素。
ZREM key member:从有序集合中移除元素。
ZRANGE key start stop:获取有序集合中指定范围的元素。
ZRANGEBYSCORE key min max:获取有序集合中分数在指定范围内的元素。
ZINCRBY key increment member:将有序集合中元素的分数增长指定的值。
1)字符串类型
字符串类型是 Redis 中最根本的数据类型,也是最常用的数据类型,它能存储任何形式的字符串,包罗二进制数据;可以用其存储用户的邮箱、JSON 化的对象甚至是一张图片;一个字符串类型键允许存储的数据的最大容量是512 MB;字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是构造字符串的形式不同;
— 字符串操作命令:
① 赋值与取值(SET / GET)
- 格式:SET key value [EX seconds] [PX milliseconds] [NX\XX]
- 格式:GET key
- 127.0.0.1:6379> SET username tom //为username赋值tom
- OK
- 127.0.0.1:6379> KEYS * //查看当前Redis服务器下有哪些key键
- 1) "username"
- 127.0.0.1:6379> GET username //对username进行取值
- "tom"
- 127.0.0.1:6379> GET password //取一个不存在的key值,提示(nil)
- (nil) //类似python的none,MySQL的null
复制代码 ② 递增 / 递减数字(INCR / DECR)
字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,Redis 提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递增后的值;递减用DECR
- 格式:INCR key //递增,默认为0
- 格式:INCRBY key increment //指定命字递增
- 格式:DECR key //递减
- 格式:DECRBY key increment //指定命字递减
留意:当要操作的键不存在时会默认键值为0,以是第一次递增后的结果是1
例如:递增整数(INCR)
- 127.0.0.1:6379> INCR num //num不存在,默认值为0,第一次递增结果为1
- (integer) 1
- 127.0.0.1:6379> INCR num //继续递增1
- (integer) 2
- 127.0.0.1:6379> GET num
- "2"
- 127.0.0.1:6379> KEYS *
- 1) "username"
- 2) "num"
复制代码 例如:当键值的值不是整数时Redis会提示错误
- 127.0.0.1:6379> SET name bar
- OK
- 127.0.0.1:6379> INCR name
- (error) ERR value is not an integer or out of range //提示错误ERROR
-
- 127.0.0.1:6379> SET name 1
- OK
- 127.0.0.1:6379> INCR name
- (integer) 2
复制代码 例如:增长指定的整数(INCRBY)
- 127.0.0.1:6379> GET num
- "2"
- 127.0.0.1:6379> INCRBY num 2 //指定数字2 递增
- (integer) 4
- 127.0.0.1:6379> INCRBY num 2
- (integer) 6
- 127.0.0.1:6379> GET num
- "6"
复制代码 例如:递减整数(DECR)
- 127.0.0.1:6379> DECR num //不指定数字,默认为1
- (integer) 5
复制代码 例如:递减指定的整数(DECRBY)
- 127.0.0.1:6379> DECRBY num 2 //指定数字2 递减
- (integer) 3
- 127.0.0.1:6379> GET num
- "3"
复制代码 ③ 向尾部追加值(APPEND)
- 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"
复制代码 ④ 获取字符串长度(STRLEN)
- 127.0.0.1:6379> STRLEN hi
- (integer) 11
复制代码 例如:中文字符返回字节数(1个汉字3个字节)
- 127.0.0.1:6379> SET name 张三
- OK
- 127.0.0.1:6379> STRLEN name
- (integer) 6
- 127.0.0.1:6379> GET name
- "\xe5\xbc\xa0\xe4\xb8\x89"
复制代码 UTF-8编码的中文,由于“张”和“三”两个字的UTF-8编码的长度都是3,以是此例中会返回6
⑤ 同时得到/设置多个键值(MSET/MGET)
- 格式:MSET key1 value1 [key2 value2…]
- 格式:MGET key1 [key2…]
- 127.0.0.1:6379> MSET username tom password 123456
- OK
- 127.0.0.1:6379> MGET username password
- 1) "tom"
- 2) "123456"
复制代码 ⑥ 判定字段是否存在(EXISTS)
- 格式:EXISTS key [key…] //存在为1,不存在为0
- 127.0.0.1:6379> EXISTS num
- (integer) 1 //true
- 127.0.0.1:6379> EXISTS number
- (integer) 0 //false
复制代码 ⑦ 字段不存在时赋值(SETNX)
- 127.0.0.1:6379> GET num
- "3"
- 127.0.0.1:6379> SETNX num 100 //赋值已存在的字段,反馈为0即false
- (integer) 0
- 127.0.0.1:6379> GET num //赋值字段未改变
- "3"
- 127.0.0.1:6379> SETNX number 100 //赋值不存在的字段,反馈为1即ture
- (integer) 1
- 127.0.0.1:6379> GET number
- "100"
复制代码 SETNX赋值,可避免覆盖已有字段的值,直接使用SET会覆盖字段的值;
⑧ 检察全部的key(KEYS *)
- 127.0.0.1:6379> KEYS *
- 1) "hi"
- 2) "username"
- 3) "name"
- 4) "number"
- 5) "password"
- 6) "num"
复制代码 ⑨ 删除字段(DEL)
- 127.0.0.1:6379> DEL number
- (integer) 1
复制代码 ⑩ 检察键的类型(TYPE)
- 127.0.0.1:6379> TYPE name
- string
复制代码 案例:字符串实践
Redis 对于键的命名并没有强制的要求,但比力好的实践是用“对象类型:对象ID:对象属性”来命名一个键;
例如:使用键【`user:1:friends`】来存储ID为1的用户的好友列表
- 127.0.0.1:6379> SET user:1:friends "tom,jerry,jack,rose"
- OK
- 127.0.0.1:6379> GET user:1:friends
- "tom,jerry,jack,rose"
复制代码
例如:假如正在编写一个博客网站,博客的一个常见的功能是统计文章的访问量,我们可以为每篇文章使用一个名为【`post:文章ID:page.view`】的键来记录文章的访问量,每次访问文章的时候使用INCR命令使相应的键值递增。
假设:有用户访问文章ID号为42的博文,则将其访问计数加1
- 127.0.0.1:6379> INCR post:33:page.view
- (integer) 1
- 127.0.0.1:6379> INCR post:33:page.view
- (integer) 2
- 127.0.0.1:6379> GET post:33:page.view
- "2"
复制代码
2)散列类型
散列类型(hash)的键值也是一种字典结构,其存储了字段(field)和字段值的映射,即字典嵌套字典;字段值只能是字符串;散列类型适合存储对象。使用对象类别和 ID 构成键名,使用字段表示对象的属性,而字段值则存储属性值。
— 散列类型操作命令:
① 赋值与取值(HSET / HGET)(HMSET / HMGET)
- 格式:HSET key field value //单个字段赋值(子键、子值)
- 格式:HGET key field //单个字段取值
- 格式:HMSET key field1 value [field2 value…] //多个字段赋值(子键、子值)
- 格式:HMGET key field1 [field2…] //多个字段取值
例如:设置单个字段
- 127.0.0.1:6379> HSET user1 name ANJ //给user1键赋值(name为子键,ANJ为子值)
- (integer) 1
- 127.0.0.1:6379> HSET user1 gender boy //给user1键赋值(gender为子键,boy为子值)
- (integer) 1
- 127.0.0.1:6379> HGET user1 name //取user1键的name子键的值
- "ANJ"
- 127.0.0.1:6379> HGET user1 gender //取user1键的gender子键的值
- "boy"
复制代码 例如:设置多个字段
- 127.0.0.1:6379> HMSET user1 email ANJ@tedu.cn phone 13545678987
- OK
- 127.0.0.1:6379> HMGET user1 email phone
- 1) "ANJ@tedu.cn"
- 2) "13545678987"
复制代码 ② 获取全部字段(HGETALL)
- 格式:HGETALL key //奇数为key,偶数为value
- 127.0.0.1:6379> HGETALL user1
- 1) "name"
- 2) "ANJ"
- 3) "gender"
- 4) "boy"
- 5) "email"
- 6) "ANJ@tedu.cn"
- 7) "phone"
- 8) "13545678987"
复制代码 ③ 判定字段是否存在并赋值(HEXISTS)
- 格式:HEXISTS key field //字段存在为1,不存在为0
- 127.0.0.1:6379> HEXISTS user1 name
- (integer) 1 //true
- 127.0.0.1:6379> HEXISTS user1 address
- (integer) 0 //false
复制代码 ④ 判定当字段不存在时赋值(HSETNX)
- 格式:HSETNX key field value
- 127.0.0.1:6379> HSETNX user1 address beijing
- (integer) 1
- 127.0.0.1:6379> HGET user1 address
- "beijing"
- 127.0.0.1:6379> HSETNX user1 address shanghai
- (integer) 0
- 127.0.0.1:6379> HGET user1 address
- "beijing"
复制代码 ⑤ 数字递增(HINCRBY)
- 格式:HINCRBY key field increment
- 127.0.0.1:6379> HINCRBY user1 age 20
- (integer) 20
- 127.0.0.1:6379> HINCRBY user1 age 1
- (integer) 21
复制代码 ⑥ 删除字段(HDEL)
- 格式:HDEL key field [field…]
- 127.0.0.1:6379> HDEL user1 age
- (integer) 1
- 127.0.0.1:6379> hget user1 age
- (nil)
复制代码 ⑦ 只获取全部字段名(HKEYS)
- 127.0.0.1:6379> HKEYS user1
- 1) "name"
- 2) "gender"
- 3) "email"
- 4) "phone"
- 5) "address"
复制代码 ⑧ 只获取全部字段值(HVALS)
- 127.0.0.1:6379> HVALS user1
- 1) "ANJ"
- 2) "boy"
- 3) "ANJ@tedu.cn"
- 4) "13545678987"
- 5) "beijing"
复制代码 ⑨ 得到字段数目(HLEN)
- 127.0.0.1:6379> HLEN user1
- (integer) 5
复制代码 案例:散列类型实践:
例如:将文章ID号为10的文章以散列类型存储在Redis中
- 127.0.0.1:6379> HSET post:10 title Linux该怎么学
- (integer) 1
- 127.0.0.1:6379> HGETALL post:10
- 1) "title"
- 2) "Linux\xe8\xaf\xa5\xe6\x80\x8e\xe4\xb9\x88\xe5\xad\xa6"
- 127.0.0.1:6379> HSET post:10 author ANJ
- (integer) 1
- 127.0.0.1:6379> HMSET post:10 date 2021-06-17 summary 'Linux example'
- OK
- 127.0.0.1:6379> HGETALL post:10
- 1) "title"
- 2) "Linux\xe8\xaf\xa5\xe6\x80\x8e\xe4\xb9\x88\xe5\xad\xa6"
- 3) "author"
- 4) "ANJ"
- 5) "date"
- 6) "2021-06-17"
- 7) "summary"
- 8) "Linux example"
- 127.0.0.1:6379>
复制代码
3)列表类型
列表类型(list)可以存储一个有序的字符串列表;常用的操作是向列表两端添加元素,或者得到列表的某一个片段;列表类型内部是使用双向链表(double linked list)实现的,获取越靠近两端的元素速度就越快;使用链表的代价是通过索引(index)访问元素比力慢;这种特性使列表类型能非常快速地完成关系数据库难以应付的场景:如社交网站的新鲜事,我们关心的只是最新的内容,使用列表类型存储,即使新鲜事的总数达到几千万个,获取其中最新的100条数据也是极快的。
— 列表类型操作命令:
① LPUSH命令用来向列表左边增长元素,返回值表示增长元素后列表的长度(LPUSH)
- 格式:LPUSH key value1 [value2…]
- 格式:LRANGE key 起始下标 结束下标
- 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命令用来向列表右边增长元素,返回值表示增长元素后列表的长度(RPUSH)
- 格式:RPUSH key value1 [value2…]
- 127.0.0.1:6379> RPUSH numbers 5 6
- (integer) 5
- 127.0.0.1:6379> LRANGE numbers -2 -1 //或者起始下标为3,结束下标为-1
- 1) "5"
- 2) "6"
复制代码 ③ 取出列表全部元素(LANGE)
- 格式:LRANGE key 起始下标 结束下标 //起始下标为0,结束下标为-1
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "3"
- 2) "2"
- 3) "1"
- 4) "5"
- 5) "6"
复制代码 ④ 从列表两端移除元素(LPOP / RPOP)
# 从列表左边移除元素
- 127.0.0.1:6379> LPOP numbers
- "3"
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "2"
- 2) "1"
- 3) "5"
- 4) "6"
复制代码 # 从列表右边移除元素
- 127.0.0.1:6379> RPOP numbers
- "6"
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "2"
- 2) "1"
- 3) "5"
复制代码 ⑤ 获取列表中元素的个数(LLEN)
- 127.0.0.1:6379> LLEN numbers
- (integer) 3
复制代码 ⑥ 删除列表中指定的值(LREM)
# LREM命令会删除列表中count值为value的元素,返回值是现实删除的元素个数。根据count值的不同,LREM命令的实行方式会略有差别。
- 当count > 0时,LREM命令会从列表左边开始删除count值为value的元素。
- 当count < 0时,LREM命令会从列表右边开始删除count值为value的元素。
- 当count = 0时,LREM命令会删除全部值为value的元素。
- 127.0.0.1:6379> LPUSH numbers 0 1 2 0 1 2 0 1 2 //numbers左边增加
- (integer) 12
- 127.0.0.1:6379> RPUSH numbers 2 1 0 2 1 0 2 1 0 //numbers右边增加
- (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) "5"
- 13) "2"
- 14) "1"
- 15) "0"
- 16) "2"
- 17) "1"
- 18) "0"
- 19) "2"
- 20) "1"
- 21) "0"
复制代码 例如:从左侧开始删除2个1
- 127.0.0.1:6379> LREM numbers 2 1 //count为2(>0 列表左边) value为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) "5"
- 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 //count为-2(<0 列表右边) value为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) "5"
- 11) "2"
- 12) "1"
- 13) "0"
- 14) "2"
- 15) "1"
- 16) "2"
- 17) "1"
复制代码 例如:删除全部的0
- 127.0.0.1:6379> LREM numbers 0 0 //count为0(=0 列表所有) value为0
- (integer) 4
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "2"
- 2) "2"
- 3) "2"
- 4) "1"
- 5) "2"
- 6) "1"
- 7) "5"
- 8) "2"
- 9) "1"
- 10) "2"
- 11) "1"
- 12) "2"
- 13) "1"
复制代码 ⑦ 得到 / 设置指定索引的元素值(LINDEX、LSET)
例如:获取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"
复制代码 ⑧ 删除指定范围之外的全部元素(LTRIM)
- 127.0.0.1:6379> LTRIM numbers 0 2 //删除指定索引0到索引2之外的所有元素
- OK
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "2"
- 2) "10"
- 3) "2"
复制代码 ⑨ 插入元素(LINSERT)
- 格式:LINSERT key before pivot value
- 格式:LINSERT key after pivot value
例如:在已存在的元素10的前面插入20
- 127.0.0.1:6379> LINSERT numbers before 10 20
- (integer) 4
- 127.0.0.1:6379> LRANGE numbers 0 -1
- 1) "2"
- 2) "20"
- 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) "2"
- 2) "30"
- 3) "20"
- 4) "10"
- 5) "2"
复制代码 案例:列表类型实践:
例如:记录最新的10篇博文
- 127.0.0.1:6379> LPUSH post:list 11 12 13
- (integer) 3
- 127.0.0.1:6379> LRANGE post:list 0 -1
- 1) "13"
- 2) "12"
- 3) "11"
复制代码
4)集合类型
集合中的每个元素都是不同的(去重),且没有顺序
① 增长元素(SADD)
- - 格式:SADD key member1 [member2…]
- - 格式:SMEMBERS key //检察集合元素
- 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"
复制代码 ② 删除元素(SREM)
- 格式:SREM key member1 [member2…]
- 127.0.0.1:6379> SREM letters a c
- (integer) 2
-
- 127.0.0.1:6379> SMEMBERS letters
- 1) "d"
- 2) "b"
复制代码 ③ 判定元素是否在集合中(SISMEMBER)
- 格式:SISMEMBER key member //0表示不存在,1表示存在
- 127.0.0.1:6379> SISMEMBER letters a
- (integer) 0
-
- 127.0.0.1:6379> SISMEMBER letters b
- (integer) 1
复制代码 ④ 集合运算(SINTER、SUNION、SDIFF)
- 格式:SINTER key1 key2 //字段之间的交集
- 格式:SUNION key1 key2 //字段之间的并集
- 格式:SDIFF key1 key2 //字段之间的差集
- 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) "c"
- 2) "b"
- 127.0.0.1:6379> SUNION s1 s2 //并集
- 1) "c"
- 2) "a"
- 3) "d"
- 4) "b"
- 127.0.0.1:6379> SDIFF s1 s2 //差集,s1有,s2没有
- 1) "a"
- 127.0.0.1:6379> SDIFF s2 s1 //差集,s2有,s1没有
- 1) "d"
复制代码 ⑤ 得到集合中元素个数(SCARD)
- 127.0.0.1:6379> SCARD letters
- (integer) 2
复制代码 ⑥ 随机得到集合中的元素(SRANDMEMBER)
- 格式:SRANDMEMBER key count //在集合key中随机取出n个不同元素
- 格式:SRANDMEMBER key -count //在集合key中随机取出n个可能相同元素
例如:在集合s1中随机取出两个不同元素
- 127.0.0.1:6379> SMEMBERS s1
- 1) "c"
- 2) "a"
- 3) "b"
- 127.0.0.1:6379> SRANDMEMBER s1 2
- 1) "a"
- 2) "b"
复制代码 例如:在集合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"
复制代码 ⑦ 集合中随机移除一个元素(SPOP)
- 127.0.0.1:6379> SPOP s1
- "a"
- 127.0.0.1:6379> SMEMBERS s1
- 1) "c"
- 2) "b"
复制代码 案例:集合实践:
例如:为文章号为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) "redis"
- 2) "python"
- 3) "nginx"
复制代码
5)有序集合类型
在集合类型的基础上有序集合类型为集合中的每个元素都关联了一个分数,这使得我们不仅可以完成插入、删除和判定元素是否存在等集合类型支持的操作,还能够得到分数最高(或最低)的前N个元素、得到指定分数范围内的元素等与分数有关的操作;固然集合中每个元素都是不同的,但是它们的分数却可以相同。有序集合类型在某些方面和列表类型有些相似:
- ① 二者都是有序的;
- ② 二者都可以得到某一范围的元素;
- 有序集合类型和列表也有着很大的区别,这使得它们的应用场景也是不同的:
- ① 列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,以是它更加适合实现如“新鲜事”或“日记”这样很少访问中间元素的应用
- ② 有序集合类型是使用散列表和跳跃表(Skip list)实现的,以是即使读取位于中间部分的数据速度也很快
- ③ 列表中不能简单地调解某个元素的位置,但是有序集合可以(通过更改这个元素的分数)
- ④ 有序集合要比列表类型更耗费内存
— 有序集合类型操作
① 增长、替换元素(ZADD、ZRANGE)
# ZADD 命令用来向有序集合中加入一个元素和该元素的分数,假如该元素已存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数;
- 格式:ZADD key score1 member1 [score2 member2…]
- 格式:ZRANGE key 起始下标 结束下标 [withscores 表现score分数]
- 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”
复制代码 ② 得到元素的分数(ZSCORE)
- 127.0.0.1:6379> ZSCORE scores tom
- "88"
复制代码 ③ 得到指定分数范围的元素(ZRANGEBYSCORE)
- 格式:ZRANGEBYSCORE key min max [withscores]
- 127.0.0.1:6379> ZRANGEBYSCORE scores 80 90 withscores
- 1) "jerry"
- 2) "85"
- 3) "tom"
- 4) "88"
复制代码 ④ 增长某个元素的分数(ZINCRBY)
- 格式:ZINCRBY key increment member
- 127.0.0.1:6379> ZINCRBY scores 3 bob
- "75"
- 127.0.0.1:6379> ZSCORE scores bob
- "78"
复制代码 ⑤ 得到集合中元素的数目(ZCARD)
- 127.0.0.1:6379> ZCARD scores
- (integer) 4
复制代码 ⑥ 得到指定分数范围内的元素个数(ZCOUNT)
- 127.0.0.1:6379> ZCOUNT scores 80 90
- (integer) 2
复制代码 ⑦ 删除元素(ZREM)
- 格式:ZREM key member [member…]
- 127.0.0.1:6379> ZREM scores bob
- (integer) 1
- 127.0.0.1:6379> ZRANGE scores 0 -1 withscores
- 1) "jerry"
- 2) "85"
- 3) "tom"
- 4) "88"
- 5) "alice"
- 6) "92"
复制代码 ⑧ 得到元素的排名(ZRANK / ZREVRANK)
- 格式:ZRANK key member //升序分列
- 格式:ZREVRANK key member //降序分列
- 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其他操作命令
1)数据操作命令
① 检察key逾期时间
- 127.0.0.1:6379> TTL name
- (integer) -1 //-1表示永不过期
复制代码 ② 设置key的逾期时间(秒)
- 127.0.0.1:6379> EXPIRE password 10 //过期时间为10秒
- (integer) 1
- 127.0.0.1:6379> TTL password //查看实时过期时间效果
- (integer) 2
- 127.0.0.1:6379> TTL password
- (integer) -2 //-2表示已过期
- 127.0.0.1:6379> EXISTS password //查看key是否存在
- (integer) 0
- 127.0.0.1:6379> SAVE //存盘
- OK
复制代码 例如:创建key的同时,设置它的逾期时间。key是user1:login,value是11111,超时时间15秒
- 127.0.0.1:6379> set user1:login 11111 ex 15 //ex为选项
- OK
- 127.0.0.1:6379> TTL user1:login
- (integer) 14
- 127.0.0.1:6379> TTL user1:login
- (integer) 9
- 127.0.0.1:6379> TTL user1:login
- (integer) 4
- 127.0.0.1:6379> TTL user1:login
- (integer) -2
复制代码
2)数据库操作命令
① 默认Redis有16个库,将name移动到1号库
- 127.0.0.1:6379> MOVE name 1
- (integer) 1
复制代码 ② 选择库(类似mysql的use)
- 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) "s1"
- 2) "numbe"
- 3) "scores"
- 4) "letters"
- 5) "user1"
- 6) "user:1:friends"
- 7) "post:10"
- 8) "password"
- 9) "numbers"
- 10) "num"
- 11) "username"
- 12) "number"
- 13) "hi"
- 14) "s2"
- 15) "post:33:page.view"
- 16) "port:10"
- 127.0.0.1:6379> FLUSHALL
- OK
- 127.0.0.1:6379> KEYS *
- (empty list or set)
复制代码 ④ 数据库内关闭Redis
- 127.0.0.1:6379> SHUTDOWN
- not connected> exit
- [root@redis redis-4.0.8]# service redis_6379 status
- cat: /var/run/redis_6379.pid: No such file or directory
- Redis is running ()
复制代码
四、修改Redis服务运行参数
1)常用参数
- ① 监听地址:默认运行在127.0.0.1上
- ② 监听端口:默认监听6379端口(不消修改)
- ③ 暗码
例如:
① 修改设置文件(/etc/redis/6379.conf)
- [root@redis ~]# vim /etc/redis/6379.conf
- # bind 127.0.0.1 //注释此行,运行在0.0.0.0上(即所有主机)
- port 6379 //端口号
- requirepass tedu.cn //密码
复制代码 ② 修改启动脚本,关机添加暗码(不添加暗码,关闭服务时提示认证失败)
- [root@redis ~]# vim +43 /etc/init.d/redis_6379
- ...
- $CLIEXEC -p $REDISPORT -a tedu.cn shutdown
- ...
复制代码 ③ 重新启动服务并测试
- [root@redis redis-4.0.8]# service redis_6379 restart
- Stopping ...
- Redis stopped
- Starting Redis server...
复制代码 # 修改前:检察服务端口状态信息
- [root@redis ~]# ss -nlptu | grep :6379
- tcp LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",pid=5030,fd=6))
复制代码 # 修改后:检察服务端口状态信息
- [root@redis ~]# ss -nlptu | grep :6379
- tcp LISTEN 0 128 *:6379 *:* users:(("redis-server",pid=14897,fd=7))
- tcp LISTEN 0 128 :::6379 :::* users:(("redis-server",pid=14897,fd=6))
复制代码 # 运行redis-cli并进行PING测试
- [root@redis ~]# redis-cli
- 127.0.0.1:6379> ping
- (error) NOAUTH Authentication required. //无认证
- 127.0.0.1:6379> exit
- [root@redis ~]# redis-cli -a tedu.cn
- 127.0.0.1:6379> ping
- PONG
- 127.0.0.1:6379> exit
复制代码
五、部署支持php和Redis的Nginx服务器
网络实行拓扑:
服务器脚色:nginx、redis
- Nginx:IP为192.168.2.10,编译安装nginx,设置php支持redis
- Redis:IP为192.168.2.11,安装Redis
步调1:安装并设置Nginx服务器
① 安装编译器
- [root@nginx ~]# yum -y install gcc pcre-devel zlib-devel
复制代码 补充:zlib是实现压缩功能的,zlib-devel是开发版的zlib
② 编译安装nginx(参考:lnmp_soft.tar.gz)
- [root@nginx lnmp_soft]# tar -xf nginx-1.12.2.tar.gz
- [root@nginx lnmp_soft]# cd nginx-1.12.2/
- [root@nginx nginx-1.12.2]# ./configure
- [root@nginx nginx-1.12.2]# make && make install
复制代码 ③ 安装php-fpm
- [root@nginx ~]# yum -y install php-fpm
- [root@nginx ~]# systemctl start php-fpm.service
- [root@nginx ~]# ss -nlptu | grep :9000
- tcp LISTEN 0 128 127.0.0.1:9000 *:* users:(("php-fpm",pid=4049,fd=0),("php-fpm",pid=4048,fd=0),("php-fpm",pid=4047,fd=0)"php-fpm",pid=4046,fd=0),("php-fpm",pid=4045,fd=0),("php-fpm",pid=4044,fd=6))
复制代码 ④ 修改设置文件,开启动态页面剖析功能
- [root@nginx ~]# 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@nginx ~]# /usr/local/nginx/sbin/nginx -t //-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@nginx ~]# /usr/local/nginx/sbin/nginx //启动服务
- [root@nginx ~]# ss -nlptu |grep :80
- tcp LISTEN 0 128 *:80 *:* users:(("nginx",pid=4119,fd=6),("nginx",pid=4118,fd=6))
复制代码 测试:
- [root@nginx ~]# vim /usr/local/nginx/html/test.php
- <?php
- echo "Hello World!\n";
- ?>
- [root@nginx ~]# curl http://127.0.0.1/test.php
- Hello World!
复制代码
步调2:设置PHP支持Redis(需要对PHP进行扩展)
① 安装php扩展
- [root@nginx ~]# yum install -y php-devel automake autoconf //简化源代码编译过程工具
复制代码 ② 安装php-redis(参考:/linux-soft/4/ php-redis-2.2.4.tar.gz)
- [root@nginx ~]# tar -xf php-redis-2.2.4.tar.gz
- [root@nginx ~]# cd phpredis-2.2.4/
- [root@nginx phpredis-2.2.4]# ls
复制代码
- [root@nginx phpredis-2.2.4]# phpize //检测php环境,生成相应的configure命令及配置信息文件/usr/bin/php-config
- Configuring for:
- PHP Api Version: 20100412
- Zend Module Api No: 20100525
- Zend Extension Api No: 220100525
- [root@nginx phpredis-2.2.4]# ls
复制代码
- [root@nginx phpredis-2.2.4]# ./configure --with-php-config=/usr/bin/php-config
- [root@nginx phpredis-2.2.4]# make && make install
复制代码
- [root@nginx phpredis-2.2.4]# ls /usr/lib64/php/modules/ //模块安装目录
- curl.so fileinfo.so json.so phar.so redis.so zip.so
复制代码 补充:在使用php的过程中,经常需要去添加一些PHP扩展库。但重新对php进行编译是比力蛮烦,以是这时候可使用phpize对php进行添加扩展。而且phpize编译的扩展库可以随时启用或停用,比力机动。实在phpize是一个运行脚本,重要作用是检测php的情况还有就是在特定的目次生成相应的configure文件,这样makeinstall之后,生成的.so文件才会主动加载到php扩展目次下面;
补充:--with-php-config,告诉phpize要建立基于哪个版本的扩展;
③ 修改php设置文件并重启服务
- [root@nginx ~]# vim /etc/php.ini //在730行下添加
- extension_dir = "/usr/lib64/php/modules" //指定php扩展模块目录
- extension = "redis.so" //扩展模块文件.so
- [root@nginx ~]# systemctl restart php-fpm
- [root@nginx ~]# php -m | grep -i redis //查看模块
- redis
复制代码 测试:
① 创建脚本,写入redis数据库
- [root@nginx ~]# vim /usr/local/nginx/html/set_redis.php
- <?php
- $redis = new redis();
- $redis->connect("192.168.2.11", "6379");
- $redis->auth("tedu.cn");
- $redis->set("username", "tom");
- ?>
复制代码 ② 创建脚本,读取redis数据
- [root@nginx ~]# vim /usr/local/nginx/html/get_redis.php
- <?php
- $redis = new redis();
- $redis->connect("192.168.2.11", "6379");
- $redis->auth("tedu.cn");
- echo $redis->get("username");
- ?>
复制代码 ③ 访问测试页面
- [root@nginx ~]# curl http://127.0.0.1/set_redis.php
- [root@nginx ~]# curl http://127.0.0.1/get_redis.php
- Tom
复制代码 ④ 在redis数据库上检察
- [root@redis ~]# redis-cli -a tedu.cn
- 127.0.0.1:6379> KEYS *
- 1) "username"
- 127.0.0.1:6379> GET username
- "tom"
复制代码
扩展知识:redis 单线程的理解
- 单线程模型
Redis客户端对服务端的每次调用都经历了发送命令,实行命令,返回结果三个过程。其中实行命令阶段,由于Redis是单线程来处置惩罚命令的,全部每一条到达服务端的命令不会立刻实行,全部的命令都会进入一个队列中,然后逐个被实行。而且多个客户端发送的命令的实行顺序是不确定的。但是可以确定的是不会有两条命令被同时实行,不会产生并发题目,这就是Redis的单线程根本模型。
- redis单线程题目
单线程指的是网络请求模块使用了一个线程(以是不需思量并发安全性),即一个线程处置惩罚全部网络请求,其他模块仍用了多个线程。
- 为什么说redis能够快速实行
- (1) 绝大部分请求是纯粹的内存操作(非常快速)
- (2) 采用单线程,避免了不须要的上下文切换和竞争条件
- (3) 非阻塞IO - IO多路复用,Redis采用epoll做为I/O多路复用技术的实现,再加上Redis自身的变乱处置惩罚模型将epoll中的连接,读写,关闭都转换为了时间,不在I/O上浪费过多的时间。
Redis采用单线程模型,每条命令实行假如占用大量时间,会造成其他线程阻塞,对于Redis这种高性能服务是致命的,以是Redis是面向高速实行的数据库。
- redis的内部实现
内部实现采用epoll,采用了epoll+自己实现的简单的变乱框架。epoll中的读、写、关闭、连接都转化成了变乱,然后使用epoll的多路复用特性,绝不在io上浪费一点时间 这3个条件不是相互独立的,特别是第一条,假如请求都是耗时的,采用单线程吞吐量及性能可想而知了。应该说redis为特殊的场景选择了合适的技术方案。
- Redis关于线程安全题目
redis现实上是采用了线程封闭的观念,把任务封闭在一个线程,自然避免了线程安全题目,不过对于需要依靠多个redis操作的复合操作来说,依然需要锁,而且有可能是分布式锁。
思维导图:
小结:
本篇章节为【第四阶段】NOSQL-DAY1 的学习笔记,这篇笔记可以开端了解到 NoSQL概述(RDBMS、NoSQL)、部署Redis服务、Redis数据类型(字符串、散列类型、列表类型、集合类型、有序集合类型)、Redis别的操作命令、修改Redis服务运行参数、部署支持PHP和Redis的Nginx服务器。除此之外推荐参考相关学习网址:
- redis 单线程的理解 - myseries - 博客园
- www.redis.cn/
- 什么是phpize及其用法 - 侯蜀黍 - 博客园
Tip:究竟两个人的智慧大于一个人的智慧,假如你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不关键羞和回避,可以向他人请教,花点时间直到你真正的理解。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |