Ref: Redis in Action
Redis是我在大约3年前为了解决一个实际问题而创造出来的:简单来说,当时我在尝试做一件使用硬盘存储关系数据库(on-disk SQL Database)无法完成的事情——在一台我能够支付得起的小虚拟机上面处理大量写人负载。
Mac OS X Redis 简洁安装
Ref: Mac环境下安装Redis
以 redis-3.2.8.tar.gz 为例:
tar -zvxf redis-3.2.8.tar.gz
# 移动解压后的文件
cp ./redis-3.2.8 /usr/local/
- 测试&安装
cd /usr/local/redis-3.2.8
sudo make test
sudo make install
- 配置
# 新建配置文件
cp /usr/local/redis-3.2.8/redis.conf /usr/local/redis-3.2.8/etc/redis.conf
# 修改配置文件
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes
- 启动 Redis Server
redis-server /usr/local/redis-3.2.8/etc/redis.conf
- 启动 Redis Client
redis-cli
Ch 1 初识Redis
1.2 Redis 数据结构
数据类型 | 存储的值 | 读写能力 |
---|---|---|
STRING | 字符串,整数,浮点数 | |
LIST | 链表,字符串 | |
SET | 无序集合,字符串 | |
HASH | 散列表 | |
ZSET | 有序列表 |
1.2.1 STRING
命令 | 行为 |
---|---|
GET | 获取 |
SET | 设置 |
DEL | 删除 |
1.2.2 LIST
命令 | 行为 |
---|---|
RPUSH | 将给定值插入列表右端 |
LRANGE | 获取列表在给定范围上的所有值 |
LINDEX | 获取列表在给定位置上的单个元素 |
LPOP | 从列表的左端弹出一个值,并返回被弹出元素 |
1.2.3 SET
命令 | 行为 |
---|---|
SADD | 添加 |
SMEMBERS | 返回所有 |
SISMEMBER | 是否存在, 1: 存在; 0: 不存在 |
SREM | 删除 |
1.2.4 HASH
命令 | 行为 |
---|---|
HSET key field value | 添加,返回值:1: 成功;0:失败 |
HGET key field | 查找 |
HGETALL | 返回所有 |
HDEL | 删除 |
1.2.5 有序集合
命令 | 行为 |
---|---|
ZADD key score member | 添加 |
ZRANGE key start stop [WITHSCORES] | 根据元素位置查找 |
ZRANGBYSCORE * key min max [WITHSCORES] [LIMIT offset count]* | 获取给定分值范围的所有元素 |
ZREM * key member [member ...]* | 删除 |
Ch 2 使用Redis构建Web应用
2.1 登录和Cookie缓存
2.4 数据行缓存
具体做法:编写一个持续运行的守护进程函数,让这个函数将指定的数据行缓存到Redis里面,并不定期地对这这些缓存进行更新。
PART 2 核心概念
Ch 3 Redis 命令
3.6 发布与订阅
3.7.1 排序
3.7.2 基本的Redis事务
Ch 4 数据安全与性能保障
Redis 持久化方式:
- 快照 Snapshotting
- 只追加文件 Append only file
创建快照命令
命令 | 行为 |
---|---|
BGSAVE | 客户端向服务器发送,启用子进程创建快照 |
SAVE | 让服务器在快照创建完成之前不再响应其他命令 |
BGSAVE | 用户配置的save选项触发 |
SAVE | Redis 通过SHUTDOWN命令接收到关闭服务器请求,或收到标准TERM信号 |
BGSAVE | 向另一个服务器发送SYNC命令开始复制 |
4.1 持久化选项
AOF持久化
命令 | 行为 |
---|---|
always | 每个Redis写命令同步 |
everysec | 每秒执行一次同步 |
no | 让操作系统决定何时同步 |
4.2 复制 Replication
命令 | 行为 |
---|---|
SLAVEOF host port | 设置Redis的主服务器 |
SALVEOF NO ONE | 取消设置Redis主服务器 |
4.4 Redis事务
命令 | 行为 |
---|---|
MULTI | 开启Redis事务,之后跟着用户传入的多个命令,最后以EXEC结束 |
WATCH | 在用户使用WATCH命令对键进行监视之后,只到用户执行EXEC命令的这段时间里面,如果有其他客户端抢先对任何被监视的键进行了替换、更新或删除等操作,那么当用户尝试执行EXEC命令的时候,事务将失败并返回一个错误,只有用户可以选择重试事务或者放弃事务,是一种乐观锁,Optimistic Locking |
UNWATCH | 可以在WATCH命令执行之后,MULTI命令执行之前对连接进行重置; |
DISCARD | 取消WATCH命令,并清空所有的已入队的命令 |
EXEC | 提交&执行已入队的命令 |
public void addUpdateContact(Jedis conn, String user, String contact) {
String acList = "recent:" + user;
Transaction trans = conn.multi();
trans.lrem(acList, 0, contact);
trans.lpush(acList, contact);
trans.ltrim(acList, 0, 99);
trans.exec();
}
Ch 5 使用Redis构建支持程序
5.4 服务的发现与配置
Ch 6 使用Redis构建应用程序组件
6.1 自动补全
使用有序集合直接在Redis内部完成自动补全的前缀计算工作。
原理:通过想有序集合添加元素来创建查找范围,并在取得范围内的元素之后移除之前添加的元素。
6.2 分布式锁
WATCH只会在数据被其他客户端抢先修改了情况才会通知执行了这个命令的客户端,而不会阻止其他客户端对其进行修改,所以这个命令被称为乐观锁。
在高负载的情况下,使用锁可以减少重试次数,降低延迟时间,提升性能并将加锁的粒度调整至合适的大小。
Dog Pile Effect
ref: Dogpile效应以及Solution
执行事务所需的时间越长,就会有越多待处理的事务互相重叠,这种重叠增加了执行单个事务所需的时间,并使得那些带有时间限制的事务失败的几率大幅度上升,最终导致所有事务执行失败的几率和进行重试的几率都大幅度上升。
6.3 计数信号量,Counting Semaphore
计数信号来量是一种锁,它可以让用户限制一项资源最多能够同时被多少个进程访问,通常用于限定能够同时使用的资源数量。
计数信号量和其他锁的区别
- 客户端获取锁失败时,客户端通常会选择继续等待
- 客户端获取技术信号来量失败时,客户通常会选择立即返回失败的结果。
6.4 任务队列
如果需要进一步减少定时任务的运行开销,那么可以在函数里面添加一个自适应方法(Adaptive Method),让函数在一段时间内都没有发现可执行的任务时,自动延长休眠时间,或者根据下一个任务的执行时间来决定休眠的时长,并将休眠时长的最大值限制为100ms,从而确保执行时间距离当前时间不远的任务可以及时被执行。
Ch 7 基于搜索的应用程序
Redis 特别适合用于解决基于搜索的问题,Search-based problem
基本搜索原理
数据预处理:建索引,Indexing,数据结构:反向索引,Inverted Indexes
- 从文档里面提取单词,语法分析,Parsing,标记化,Tokenization