《Redis实战》读书笔记
Redis的重要性不必多说,所以我将从0开始学习Redis,并记录下来。我将把《Redis实战》这本书作为我的入门书籍,没有多少原因,找书的时候发现这个比较适合我,既介绍了基础的语法等知识,也用一些实战项目来应用Redis,下面开始学习之旅吧~~~
Ubunut下Redis安装
书上介绍了Linux, OS X, Windows三种系统下的Redis安装步骤,我自己的电脑为Ubuntu 16.04,所以只记录Linux相关步骤。
简单方法
apt-get install redis-server
不推荐这个方法,因为根据Ubuntu版本的不同,这种安装方法会安装旧版本的Redis。
源码编译安装
- 安装构建工具
sudo apt-get update
sudo apt-get install make gcc python-dev
-
下载Redis源码
- 从Redis官网下载最新stable版本的Redis源码
- 解压源码,编译,安装并启动Redis
~:$ tar -xzf redis-4.0.7.tar.gz 解压源码 ~:$ cd redis-4.0.7/ ~/redis-4.0.7:$ make 编译Redis cd src && make all ... 编译信息 ... 注意观察编译信息,不应看到错误 make[1]: leaving directory '~/redis-4.0.7/src ~/redis-4.0.7:$ sudo make install 安装Redis cd src && make install ... 安装信息不应有错 make[1]: leaving directory '~/redis-4.0.7/src ~/redis-4.0.7:$ redis-server redis.conf 启动Redis
3.下载安装Python语言的Redis客户端库
pip3 install redis hiredis
hiredis包是一个C库,提高Python的Redis客户端速度。
在Ipython中测试是否可以连接(省略)
问题
我的步骤跟书上不是完全一样,以上操作是根据我自己的实际操作写出。我在Ipython中连接redis失败,因为redis没有启动。原来用redis-server
启动不能够保持Redis在后台一直运行,在终端被关闭时就关闭,有两种解决办法。
运行命令时添加'&',
redis-server &
修改redis.conf文件,将默认的daemonize no改为yes
第一部分 入门
第一部分包括前两章,前两章简单的介绍了一下Redis,以及两个入手的小例子。
Redis是一个速度非常快的非关系数据库,是一个内存数据库。因此Redis不需要事先定义表结构等操作,Redis提供了5种不同类型的数据结构来帮助我们更高效的解决问题。这五种数据结构分别是:
- STRING 字符串
- LIST 列表
- SET 集合
- HASH 散列
- ZSET 有序集合
前两章包括了两个例子,一个是在博客网站上对文章进行评分和展示,一个是用Redis构建Web应用,因为还没有讲解Redis命令,且对Redis的数据结构还不够熟悉,看示例代码时有些命令看得有些费力,但是命令的理解不是前两章的重点,代码的整体思路也是能看看明白的,重点在于观念的改变,理解Redis可以用在什么场合,以及如何使用Redis。书本配套示例代码
在关系数据库中,我们遇到问题经常需要扭曲问题来适应数据库,但是Redis的数据结构可以自然而然的应用于我们的问题。
命令
第二部分深入介绍了Redis的命令,每个不同的数据结构有不同的命令,整体的掌握这些数据结构以及命令才能恰当地将Redis应用到具体的问题,达到更好的优化效果。
字符串 String
字符串是一个由字节组成的序列,可以存储字符串,整数或者浮点数,与编程语言中的字符串相去不大。
处理数值
- set key value 将键key的值设为value
- get key 获取存在键key里的值
- del key 删除key这个键值对
- incr key key存储的值加1(若key不存在,默认初值为0)
- decr key key存储的值减1(同上)
- incrby key amount key存储的值加整数amount(同上)
- decrby key amount key存储的值减整数amount(同上)
- incrbyfloat key amount 浮点数amount
处理子串
- append key value 将value追加到key值尾端
- getrane key start end 获取偏移量start到end(包括两端)的所有字符组成的子串
- setrange key start value 将从start偏移量开始的子串设置为value
列表 LIST
列表可以有序的存储多个字符串。
- rpush key value [value ...] 将一个或多个value推入列表右端
- lpush key value [value ...]
- rpop key 移除并返回列表最右端的值
- lpop key
- lindex key 返回列表中偏移量为offset的元素
- lrange key start end 返回列表从start到end的所有元素(包括两端)
- ltrim key start end 保留列表从start到end的所有元素(包括两端)
集合
集合以无序的方式存储多个各不相同的元素。
- sadd key item [item ...] 将一个或多个元素添加到集合key,返回被添加元素不在原始集合的元素数量
- srem key item [item ...] 从集合里移除一个或多个元素,返回被移除的元素数量
- sismember key item 检查item是否在集合Key中
- scard key 返回集合包含元素数量
- smembers 返回集合的所有元素
- srandmember key [count] 从集合里随机返回一个或多个元素。当count为正,元素不会重复,为负时可能重复
- spop key 从集合key随机移除一个元素并返回
- smove source-key dest-key item 如果集合source-key包含item,移除item并添加到dest-key集合;成功移除返回1,否则0
- sdiff key [key ...] 返回那些存在第一个集合,但不在其他集合的元素(差集)
- sdiffstore dest-key key [key ...] 将上一条命令的元素存储在dest-key集合中
- sinter key [key ...] 返回同时存在于所有集合的元素(交集)
- sinterstore dest-key key [key ...] 将上一条命令的元素存储在dest-key集合中
- sunion key [key ...] 返回至少在一个集合中出现过的元素(并集)
- sunionstore dest-key key [key ...] 将上一条命令的元素存储在dest-key集合中
散列 HASH
将多个键值对存储在一个键值里。
- hmget key-name key [key ...] 从散列里获取一个或多个值
- hmset key-name key [key ...] 为散列设置一个或多个值
- hdel key-name key [key ...] 删除,并返回成功删除数量
- hlen key-name 返回散列包含的键值对数量
- hexists key-name key 检查key键是否在散列中
- hkeys key-name 获取散列的所有键
- hvals key-name 获取散列的所有值
- hgetall key-name 获取散列的所有键值对
- hincrby key-name key increment 将键Key存储的值加上整数increment
- hincrbyfloat key-name key increment 浮点数
有序集合 ZSET
与散列存储着键和值之间的映射类似,有序集合存储着成员与分值之间的映射。
- zadd key-name score member [score member ...] 将带有给定分值score的成员member添加到有序集合
- zrem key-name member [member ...] 从有序集合删除给定成员,返回被移除成员数量
- zcard key-name 返回有序集合成员数量
- zincrby key-name increment member 将member的分值加上increment(python客户端参数位置有变化)
- zcount key-name min max 返回分值介于min和max之前的成员数量
- zrank key-name member 返回成员member在有序集合中的排名(从0开始)
- zscore key-name member 返回成员member的分值
- zrange key-name start stop [withscores] 返回排名介于start和stop之间的成员(包括两端),如果加上withscores,则成员的分值一并返回
- zrevrank key-name member 返回member的排名,成员按照分值从大到小排列
- zrevrange key-name start stop [withscores] 返回start到stop范围内的成员,按值从大到小排列
- zrangebyscore key min max [withscores] 返回分值介于min,max间的所有成员
- zrevrangebyscore key min max [withscores] 返回分值介于min,max间的所有成员,按值从大到小
- zremrangebyrank key-name start stop 移除排名介于start,stop的成员
- zremrangebyscore key-name min max 移除分值介于min,max的成员
- zinterstore dest-key key-count key [key...] [weights weight [weight]] [aggregate sum|min|max] 对给定有序集合执行类似于集合的交集运算
- zunionstore dest-key key-count key [key...] [weights weight [weight]] [aggregate sum|min|max] 执行并集运算
关于5种数据结构的常用命令,上面已经列出来很多,但是其实还有很多。我个人觉得记住所有的是有难度的(记性差),这些命令的命名规则还是有许多相似之处,可以方便记忆,但是更好的办法是记住一些常用的,然后了解Redis的命令可以实现什么样的操作,当需要这样的操作时再去查命令。
其他命令
- sort source-key 相当于关系数据库的order by(有很多可选参数)
- persist key-name 移除键的过期时间
- ttl key-name 查看距离过期时间还有多少秒
- expire key-name seconds 让给定键在指定秒数之后过期
- expireat key-name timestamp 将给定键的过期时间设置为给定的UNIX时间戳
- 事务命令
- 发布订阅命令
更多命令参考 官网
数据安全与性能保障
与关系数据库类似,Redis也需考虑数据的安全,需要备份数据,保障出现故障后能够全部或最大化的恢复损失。但与关系数据库不同的是,Redis是内存数据库,数据是存储在内存里的,在程序崩溃、重启等情况下内存数据就会丢失,还需要考虑数据持久化,即将内存的数据写入磁盘。Redis提供了两种数据持久化的方法,一种为快照持久化,另一种为只追加文件(append-only file AOF)。可以单独使用,或者同时使用,甚至都不使用。
持久化后的数据就是安全的了吗?不是的,现在面临的就是和关系数据库类似的备份数据问题了。需要将数据复制到多台服务器来保证数据安全,这就是主从服务器的一部分。
Redis复制启动过程
步骤 | 主服务器操作 | 从服务器操作 |
---|---|---|
1 | (等待命令进入) | 连接(重连接)主服务器,发送SYNC命令 |
2 | 开始执行BGSAVE,并使用缓冲区记录BGSAVE之后执行的所有写命令 | 根据配置决定是否使用现有数据来处理客户端请求,还是向客户端返回错误 |
3 | BGSAVE执行完毕,向从服务器发送快照文件,在发送期间继续使用缓冲区记录被执行的写命令 | 丢弃旧数据,载入主服务器的快照文件 |
4 | 快照发送完毕,向从服务器发送存储在缓冲区里的写命令 | 完成对快照文件的解释操作,像往常一样开始接受命令请求 |
5 | 缓冲区存储的写命令发送完毕;现在开始,每执行一个写命令,向从服务器发送相同的写命令 | 执行主服务器发来的所有存储在缓冲区里面的写命令,并开始接受并执行主服务器发来的每个写命令 |
性能优化
大家都知道在程序运行过程中,IO访问速度是远远不如CPU计算速度的,在Redis中也有类似的问题存在。Redis客户端发送命令到Redis服务器、Redis服务器响应发送到客户端的过程是相对较慢的,因此要减少客户端与服务器的通信次数,通过使用pipeline技术将多个命令放在一次通信过程中会大大提高Redis的效率。
最后
写到这其实只占了书本篇幅的2/5,但是后面的篇幅大多数都是结合着具体例子,介绍了一些Redis常用场景,通过分析例子需求实现的一个个小功能,是一些Python代码片段,包含着Redis命令和逻辑处理,记录下来的意义不大,因为实际需求总在发生变化,总是不同的。
Redis的相关知识肯定远远不止这些,这些只是最最基础的,我以后可能会继续分享Redis的相关文章,学习过程等等。一起加油!!!