Redis 概述
Redis 是一个开源的内存数据结构存储器, 用作数据库, 缓存和消息代理.
它支持的数据结构类型有
- 字符串string,
- 哈希 heshes,
- 列表 lists, 集合 sets,
- 带有范围查询的顺序集合 sorted set,
- 位图 bitmap,
- 超级日志hyperloglogs,
- 带有半径查询的地理空间索引 geospatial indexes
Redis 内置了复制, Lua脚本, LRU 回收, 事务和不同级别的持久化, 通过 Redis sentinel 和 Redis cluster 自动分区 提供了高可靠性
最高值
- 读 110000 次/s
- 写 81000 次/s
一般推荐 QPS 30000, 如果QPS 太高的话, 比如 60000 次/s, CPU过于繁忙, 软中断过多, 性能反而下降
Redis 快速上手
安装
step1. brew install redis
$ find /usr/local/Cellar/redis/3.0.4/
./bin
./bin/redis-benchmark # redis performance benchmark tool
./bin/redis-check-aof # aof file repair tool
./bin/redis-check-dump # rdb file check tool
./bin/redis-cli # redis client
./bin/redis-sentinel
./bin/redis-server # redis server
./COPYING
./homebrew.mxcl.redis.plist
./INSTALL_RECEIPT.json
./README
或者通过源码安装
wget https://github.com/antirez/redis/archive/3.2.10.tar.gz
make
copy redis.conf redis-server /opt/redis
step2. ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents
卸载
$ brew uninstall redis
$ rm ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
使用
- 默认端口是6379
- 启动
## 指定端口启动
redis-server --port 6666
## 指定配置文件启动
redis-server /usr/local/etc/redis.conf
## 使用 launchctl 启动
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
停止
redis-cli shutdown
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
配置文件
redis-server
redis.conf
- bind $IPAddress
- protected-mode
- requirepass
- daemonize yes
- port 6666 # default poort is 6379
- pidfile redis_6666.pid
redis-cli -h $host -p $port
auth $pass
config get ...
config set ...
文件格式
- rdb 数据文件
- aof 更新日志
命令行工具
redis-cli -h 127.0.0.1 -p 6379
redis-cli ping
redis-cli
部署模式
- one node
- master-slave
基本命令
赋值 set key value
取值 get key
递增 inc key
递增指定整数 incby key increment
递增指定浮点数 incbyfloat key increment
递减 decr key
-
追加值 append key value
127.0.0.1:6379> set greeting good
OK
127.0.0.1:6379> append greeting " morning"
(integer) 12
127.0.0.1:6379> get greeting
"good morning" 获取字串长度 strlen key
同时设置和获取多值
mset key1 val1 key2 val2
mget key1 key2位操作
getit key offset
setbit key offset value
bitcount key [start] [end]
复合类型
哈希
就象一个 map
hset key field value
hget key
hmset key fieldname1, fieldvalue1
hmget key fieldname1, fieldname2
hgetall key
hkeys
hvals
hdel
列表
- 添加元素
从左首添加 lpush key values
lpush booklist posa1, posa2, posa2, gof
lrange booklist
从右首添加 rpush key values
- 弹出元素
从左首删除 lpop key
从右首删除 rpop key
列表个数
llen key列表子集
lrange key start stop
lrange booklist 0, 2
- 列表元素
lindex key index
lset key index value
集合
添加元素
sadd key members删除元素
srem key members列表元素
smembers key查询元素是否存在
smember key member集合间运算
sdiff keys
sinter keys
sunion keys
有序集合
高级功能
事务
要么都执行, 要么都不执行
multi
commands...
exec
Watch
Sort
TTL
队列Queue
生产者使用 rpush 来生产数据
消费者使用 lpop 来消费数据
- Producer lpush
- Cusumer roop
优先级队列
blpop
lpush
发布/订阅 Pub/Sub
发布及订阅一个频道, 只是消息的一个分派, 如果无人订阅这个频道, 这条数据也不会保存
publish channel message
subscribe channels
unsubscribe channels
Redis 事务
事务开始 multi
后续操作都会入队
执行事务 exec
取消/回滚事务 discard
持久化
RDB 方式
根据时间和改动的次数存储内存中的快照到磁盘中去
AOF 方式
AOF - Append Only File
appendonly yes
复制
主从方式 master-slave, 通过 TCP 连接将数据从master同步到slave
- master 可读可写, 自动将数据变化同步给slave
- slave 只读, 接收master 同步过来的数据
![Uploading image_933626.png . . .]
配置方式
vi redis.conf
slaveof master_ip_port
安全
requirepass xxx
通信协议
统一请求协议 unified request protocol
简单协议
Redis Cluster
工具
- phpRedisAdmin
类似于phpMyAdmin
客户端库
列举一些我懂的语言写的客户端库 C/C++, Java, PHP and Node,
Ruby 和 Go 准备今年先入个门
Language | Library |
---|---|
C | hiredis |
java | Jedis |
Node | node_redis |
Python | redis-py |
PHP | phpredis |
Ruby | redis-rb |
Go | Radix |
附录
Java Client Jedis 使用
- maven configuration
redis.clients
jedis
2.8.0
jar
compile
- 代码片断
Jedis jedis = null;
try {
jedis = pool.getResource();
/// ... do stuff here ... for example
jedis.set("foo", "bar");
String foobar = jedis.get("foo");
jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike");
Set sose = jedis.zrange("sose", 0, -1);
} finally {
if (jedis != null) {
jedis.close();
}
}
/// ... when closing your application:
pool.destroy();
Java 代码 BasicRedisClient
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class BasicRedisClient {
protected final Logger LOG = LoggerFactory.getLogger(getClass());
private final JedisPool jedisPool;
public BasicRedisClient(JedisPool jPool) {
this.jedisPool = jPool;
}
public void setValue(String key, String value, int ttl) {
Jedis jedis = jedisPool.getResource();
try {
jedis.set(key, value);
jedis.expire(key, ttl);
} catch (Exception e) {
LOG.warn("Failed to set value in redis: ", e.getStackTrace()[0]);
} finally {
jedisPool.returnResource(jedis);
}
}
public String getValue(String key) {
String rValue = null;
Jedis jedis = jedisPool.getResource();
try {
rValue = jedis.get(key);
} catch (Exception e) {
LOG.warn("Failed to get value in redis: ", e.getStackTrace()[0]);
} finally {
jedisPool.returnResource(jedis);
}
return rValue;
}
public boolean removeValue(String key) {
boolean rValue = false;
Jedis jedis = jedisPool.getResource();
try {
rValue = (jedis.del(key) > 0);
} catch (Exception e) {
LOG.warn("Failed to remove value in redis: ", e.getStackTrace()[0]);
} finally {
jedisPool.returnResource(jedis);
}
return rValue;
}
}
参考资料
书籍
- 国人写的一本 Redis入门指南
还有两本没看
- Redis 实战
- Redis设计与实现
链接
- 官方站点: http://redis.io
- Redis sentinel: https://redis.io/topics/sentinel
- https://redis.io/commands/setnx