Redis 入门

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<string, string>

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
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>    
  • 代码片断
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<String> 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;
    }
}

参考资料

书籍

还有两本没看

链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容