roll-in-redis
前言
推荐看三本书,分别是《redis入门指南(第二版)》,《redis设计与实现》和 《redis实战》
学习路线参考 redis学习路线,huangz大牛写的~
redis in action
第一章
1.1 redis简介
1.1.1 redis 与其它数据库和缓存服务器的比较
1.1.2 附加特性
在使用类似Redis这样的内存数据库时,一个首先要考虑的问题就是“当服务器被关闭时,服务器存储的数据将何去何从呢?”Redis拥有两种不同形式的持久化方法,它们都可以用小而紧凑的格式将存储在内存中的数据写入到磁盘:第一种持久化方法为时间点转储(point-in-time dump),转储操作既可以在“指定时间段内有指定数量的写操作执行”这一条件被满足时执行,又可以通过调用两条转储到磁盘(dump-to-disk)命令中的任何一条来执行;第二种持久化方法将所有修改了数据库的命令都写入到一个只追加(append-only)文件里面,用户可以根据数据的重要程度,将只追加写入设置为从不同步(sync)、每秒钟同步一次或者每写入一个命令就同步一次。
另外,尽管Redis的性能很好,但受限于Redis的内存存储设计,有时候只使用一台Redis服务器可能没有办法处理所有请求。因此,为了扩展Redis的读性能,并为Redis提供故障转移(failover)支持,Redis实现了主从复制特性:执行复制的从服务器会连接上主服务器,接收主服务器发送的完整数据库的初始副本(copy);之后主服务器执行的写命令,都会被发送给所有连接着的从服务器去执行,从而实时地更新从服务器的数据集。因为从服务器包含的数据会不断地进行更新,所以客户端可以向任意一个从服务器发送读请求,以此来避免对主服务器进行集中式的访问。
1.2数据结构简介
redis提供的5种结构
1.3简单的文章投票网址的后端
参见原书
1.4 小结
Redis是一个可以用来解决问题的工具,它拥有其他数据库所不具备的数据结构,并且因为它是内存数据库(这使得Redis的速度非常快),具有远程(这使得Redis可以连接多个客户端和服务器)、持久化(这使得服务器可以在重启之后仍然保持重启之前的数据)和可扩展(通过主从复制和分片)等多个特性,使得用户可以以熟悉的方式来为各种不同的问题构建解决方案(如考虑使用哪种Redis数据结构来解决这个问题比较好)。
第二章使用redis构建Web应用
一个Web服务器对请求进行响应的典型步骤如下:
- 服务器对客户端发来的请求(request)进行解析。
- 请求被转发给一个预定义的处理器(handler)。
- 处理器可能会从数据库中取出数据。
- 处理器根据取出的数据对模板(template)进行渲染(render)。
- 处理器向客户端返回渲染后的内容作为对请求的响应(response)。
2.1登陆和cookie缓存
对于用来登录的cookie,有两种常见的方法可以将登录信息存储在cookie里面:一种是签名(signed)cookie,另一种是令牌(token)cookie。
签名cookie通常会存储用户名,可能还有他们的用户ID、用户最后一次成功登录的时间,以及网站觉得有用的其他任何信息。除了用户的相关信息之外,签名cookie还包含一个签名,服务器可以使用这个签名来验证浏览器发送的信息是否未经改动(比如将cookie中的登录用户名改成另一个用户)。
令牌cookie会在cookie里面存储一串随机字节作为令牌,服务器可以根据令牌在数据库中查找令牌的拥有者。随着时间的推移,旧令牌会被新令牌取代。
2.2使用redis实现购物车
使用cookie实现购物车——也就是将整个购物车都存储到cookie里面的做法非常常见,这种做法的一大优点是无须对数据库进行写入就可以实现购物车功能,而缺点则是程序需要重新解析和验证(validate)cookie,确保cookie的格式正确,并且包含的商品都是真正可购买的商品。cookie购物车还有一个缺点:因为浏览器每次发送请求都会连cookie一起发送,所以如果购物车cookie的体积比较大,那么请求发送和处理的速度可能会有所降低。
在这里,可以将购物车的信息存储到Redis里面,并且使用与用户会话cookie相同的cookie ID来引用购物车。购物车的定义非常简单:每个用户的购物车都是一个散列,这个散列存储了商品ID与商品订购数量之间的映射。
2.3网页缓存
|
|
2.4 数据行缓存
为了展示数据行缓存的作用,我们假设Fake Web Retailer为了清空旧库存和吸引客户消费,决定开始新一轮的促销活动:这个活动每天都会推出一些特价商品供用户抢购,所有特价商品的数量都是限定的,卖完即止。在这种情况下,网站是不能对整个促销页面进行缓存的,因为这可能会导致用户看到错误的特价商品剩余数量,但是每次载入页面都从数据库里面取出特价商品的剩余数量的话,又会给数据库带来巨大的压力,并导致我们需要花费额外的成本来扩展数据库。
为了应对促销活动带来的大量负载,我们需要对数据行(即页面所需要的数据信息)进行缓存,具体的做法是:编写一个持续运行的守护进程函数,让这个函数将指定的数据行缓存到Redis里面,并不定期地对这些缓存进行更新。
2.5 网页分析
第三章redis
3.1字符串
在redis中,字符串可以存储以下三种类型的值:字符串,整数,浮点数。
字符串有两项操作,一项是自增自减,这个是适用于数字,常用的命令有INCR,DECR,INCRBY,DECRBY,INCRBYFLOAT等等;还一项是对字符串的部分内容进行读取或写入,即截断操作,主要命令有APPEND,GETRANGE,SETRANGE,GETBIT,SETBIT,BITCOUNT,BITOP等等。
3.2 列表
3.3 集合
3.4散列
HGET
命令和HSET
命令分别是HMGET
命令和HMSET
命令的单参数版本(MGET和GET也是如此,M表示多个参数的意思),这些命令的唯一区别在于单参数版本每次执行只能处理一个键值对,而多参数版本每次执行可以处理多个键值对。
3.5有序集合
默认排序是从小到大,升序排列。ZREV*
开头的命令就是按照降序排序。
命令 | 用例和描述 | ||
---|---|---|---|
ZADD | ZADD key-name score member [score member …]——将带有给定分值的成员添加到有序集合里面。Redis标准是先输入分值、后输入成员,但python正好相反。 | ||
ZINTERSTORE | ZINTERSTORE dest-key key-count key [key …][WEIGHTS weight [weight …]] [AGGREGATE SUM\ | MIN\ | MAX]——对给定的有序集合执行类似于集合的交集运算 |
ZUNIONSTORE | ZUNIONSTORE dest-key key-count key [key …][WEIGHTS weight [weight …]] [AGGREGATE SUM\ | MIN\ | MAX]——对给定的有序集合执行类似于集合的并集运算 |
ZREVRANK | ZREVRANK key-name member——返回有序集合里成员member所处的位置,成员按照分值从大到小排列 |
- ZINTERSTORE和ZUNIONSTORE默认使用的聚合函数为sum,用户可以在执行并集运算和交集运算的时候传入不同的聚合函数,共有 sum、min、max 三个聚合函数可选。
- 用户还可以把集合作为输入传给ZINTERSTORE和ZUNIONSTORE,命令会将集合看作是成员分值全为1的有序集合来处理。
3.6 发布与订阅
redis的发布与订阅有以下两个问题:
1.不稳定
对于旧版Redis来说,如果一个客户端订阅了某个或某些频道,但它读取消息的速度却不够快的话,那么不断积压的消息就会使得Redis输出缓冲区的体积变得越来越大,这可能会导致Redis的速度变慢,甚至直接崩溃。也可能会导致Redis被操作系统强制杀死,甚至导致操作系统本身不可用。新版的Redis不会出现这种问题,因为它会自动断开不符合client-output-buffer-limit pubsub
配置选项要求的订阅客户端。
2.数据传送不是很可靠
如果客户端在执行订阅操作的过程中断线,那么客户端将丢失在断线期间发送的所有消息。
3.7其它命令
3.7.1排序
命令 | 用例和描述 | |
---|---|---|
SORT | `SORT source-key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC\ | DESC] [ALPHA] [STOREdest-key]` ——根据给定的选项,对输入列表、集合或者有序集合进行排序,然后返回或者存储排序的结果 |
使用SORT
命令提供的选项可以实现以下功能:根据降序而不是默认的升序来排序元素;将元素看作是数字来进行排序,或者将元素看作是二进制字符串来进行排序(比如排序字符串'110'
和'12'
的结果就跟排序数字110
和12
的结果不一样);使用被排序元素之外的其他值作为权重来进行排序,甚至从输入的列表、集合或者有序集合那里获取外部值等等。
|
|
3.7.2 基本的redis事务
什么是redis的基本事务?
Redis的基本事务(basic transaction)需要用到MULTI
命令和EXEC
命令,这种事务可以让一个客户端在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚(rollback)的事务不同,在Redis里面,被MULTI
命令和EXEC
命令包围的所有命令会一个接一个地执行,直到所有命令都执行完毕为止。当一个事务执行完毕之后,Redis才会处理其他客户端的命令。
要在Redis里面执行事务,我们首先需要执行MULTI
命令,然后输入那些我们想要在事务里面执行的命令,最后再执行EXEC
命令。当Redis从一个客户端那里接收到MULTI
命令时,Redis会将这个客户端之后发送的所有命令都放入到一个队列里面,直到这个客户端发送EXEC
命令为止,然后Redis就会在不被打断的情况下,一个接一个地执行存储在队列里面的命令。从语义上来说,Redis事务在Python客户端上面是由流水线(pipeline)实现的:对连接对象调用piepline()
方法创建一个事务,在这个事务正确使用的情况下,会用MULTI
和EXEC
包裹起一连串的多个命令。另外,为了减少Redis与客户端之间的通信往返次数,提升执行多个命令时的性能,Python的Redis客户端会存储起事务包含的多个命令,然后在事务执行时一次性地将所有命令都发送给Redis。
3.7.3 键的过期时间
命令 | 示例和描述 |
---|---|
PERSIST | PERSIST key-name ——移除键的过期时间 |
TTL | TTL key-name ——返回给定键距离过期还有多少秒 |
EXPIRE | EXPIRE key-name seconds ——让键key-name 在给定的 seconds秒之后过期 |
EXPIREAT | EXPIREAT key-name timestamp ——将给定键的过期时间设置为给定的UNIX时间戳 |
第四章 数据安全与性能保障
待续…