设为首页 收藏本站
云服务器等爆品抢先购,低至4.2元/月
查看: 1598|回复: 0

[经验分享] redis入门到精通

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2017-3-24 17:30:35 | 显示全部楼层 |阅读模式
redis3.2.8学习
  • (1)redis安装及简单测试

        官网地址为:https://redis.io/download

        $ wget http://download.redis.io/releases/redis-3.2.8.tar.gz
        $ tar xzf redis-3.2.8.tar.gz
        $ cd redis-3.2.8
        $ make

        启动服务
        $ src/redis-server

        redis-server /root/soft/redis/sbin/redis.conf &

        查看进程
        ps -ef | grep 6379

        交互式命令
        $ src/redis-cli
        redis> set foo bar
        OK
        redis> get foo
        "bar"

        bgsave  命令持久化数据到磁盘

        或者
        [iyunv@node1 redis]# redis-cli set id 1
        OK
        [iyunv@node1 redis]# redis-cli get id
        "1"

        redis-cli  -h 192.168.175.29 -p 6379

(2)redis.conf配置文件解读(重要参数)

#bind 127.0.0.1

关闭保护模式 远程可以连接
protected-mode no

port 6379

日志隔离级别
loglevel notice

#log文件名称
logfile "mylog.txt"

默认数据库个数
databases 16

#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed

快照
save 900 1
save 300 10
save 60 10000

#DB文件名字
# The filename where to dump the DB
dbfilename dump.rdb

#目录
# Note that you must specify a directory here, not a file name.
dir /root/soft/redis/sbin/db

(3)String 结构
中文网学习地址 http://www.redis.cn/commands.html#string

一:String 结构
Java String
C#   String   =>         char[]的封装。。。
Redis C语言实现  char[] 进行了封装。。。   append,length,substring,set,get。。。。setrange => replace...

二: 最常用命令。。。
官网学习地址 http://www.redis.cn/documentation.html  翻译比较全,比较新

《1》 set/get 命令    [对string进行赋值]  时间复杂度:O(1)
SET key value [EX seconds] [PX milliseconds] [NX|XX]
GET key   【nil】 =>lua

应用场景分布式锁。。。。【zookeeper】 相对来说重量级。
通过对username的赋值的返回值来判断是否获取到了一个分布式锁。。。
set username jack NX =》 如果返回ok,说明获得到了锁。。。
set username mary NX =》 如果返回nil,说明没有获取到锁。。。


《2》 Incr,Decr,    =>自增或者自减1     【 i++, i-- 】
127.0.0.1:6379> set mykey "10"
OK
127.0.0.1:6379> object encoding mykey
"int"
127.0.0.1:6379>
127.0.0.1:6379> incr mykey
(integer) 11
127.0.0.1:6379> get mykey
"11"

127.0.0.1:6379> get mykey
"11"
127.0.0.1:6379>
127.0.0.1:6379> decr mykey
(integer) 10
127.0.0.1:6379> get mykey
"10"

IncrBy,DecrBy =>自增或者自减去指定的值 【 i=i + xx,  i=i - xx 】
127.0.0.1:6379> get mykey
"10"
127.0.0.1:6379> incrby mykey 6
(integer) 16
127.0.0.1:6379> get mykey
"16"

127.0.0.1:6379> get mykey
"16"
127.0.0.1:6379> decrby mykey 9
(integer) 7
127.0.0.1:6379> get mykey
"7"
127.0.0.1:6379>

Redis中的String不是string类型。。。   如果存放到string中的value是int,那么其实在内部还是用int的。。。
从encoding可以看出。。。      

RedisObject中有一个type属性,
有一个encoding属性。。。
有一个ptr属性。 => SDS

查看类型 OBJECT ENCODING
127.0.0.1:6379> object encoding username
"embstr"

127.0.0.1:6379> set mykey "10"
OK
127.0.0.1:6379> object encoding mykey
"int"
从一个简单的String类型中,我们发现有int,embstr.... 【性能优化】
三、String过期操作
一:String 过期操作  一些 工具函数
Redis  单线程的内存字典服务器。。。 过期时间  =》 [mamcache]  kv结构。
SET key value [EX seconds] [PX milliseconds] [NX|XX]
缓存,和memcache做一样的功能。。。
ttl username 用于查看当前还剩多少秒。。。 NativeCache

EX seconds – Set the specified expire time, in seconds.
PX milliseconds – Set the specified expire time, in milliseconds.
NX – Only set the key if it does not already exist.
XX – Only set the key if it already exist.
EX seconds – 设置键key的过期时间,单位时秒
PX milliseconds – 设置键key的过期时间,单位时毫秒
NX – 只有键key不存在的时候才会设置key的值
XX – 只有键key存在的时候才会设置key的值

设置一个key mykey1值为"hello" 过期时间为5s
127.0.0.1:6379> set mykey1 "hello" ex 5
OK
127.0.0.1:6379> get mykey1
"hello"
查看用于查看当前还剩多少秒
127.0.0.1:6379> set mykey1 "hello" ex 5
OK
127.0.0.1:6379> ttl mykey1
(integer) 4

PSETEX key milliseconds value  《=》 Set key value [PX milliseconds]  
PSETEX和SETEX一样,唯一的区别是到期时间以毫秒为单位,而不是秒

127.0.0.1:6379> PSETEX mykey 10000 "Hello"
OK
127.0.0.1:6379> get mykey
"Hello"
127.0.0.1:6379> pttl mykey
(integer) 2189

SETEX key seconds value   《=》   Set key value [EX seconds]

127.0.0.1:6379> setex mykey 10 "hello"
OK
127.0.0.1:6379> get mykey
"hello"
一样用法

二:String  
1. len => StrLen   时间复杂度:O(1)
返回key的string类型value的长度。如果key对应的非string类型,就返回错误
127.0.0.1:6379> set mykey "abcdef"
OK
127.0.0.1:6379> get mykey
"abcdef"
127.0.0.1:6379> STRLEN mykey
(integer) 6

2. substring => GetRange   => getRange username 0 2
时间复杂度:O(N) N是字符串长度,复杂度由最终返回长度决定,但由于通过一个字符串创建子字符串是很容易的,它可以被认为是O(1)。
127.0.0.1:6379>  SET mykey "This is a string"
OK
127.0.0.1:6379> getrange mykey 0 3
"This"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> getrange mykey -3 -1
"ing"
127.0.0.1:6379> getrange mykey 0 -1
"This is a string"
127.0.0.1:6379> getrange mykey 10 100
"string"
127.0.0.1:6379>

3. replace => SetRange 


SETRANGE key offset value  =>
127.0.0.1:6379> SET key1 "Hello World"
OK
127.0.0.1:6379> SETRANGE key1 6 "Redis"
(integer) 11
127.0.0.1:6379>
127.0.0.1:6379> get key1
"Hello Redis"



127.0.0.1:6379> get username
"jack"
127.0.0.1:6379> setRange username 4 "12345"
(integer) 9
127.0.0.1:6379> get username
"jack12345"

Append命令
127.0.0.1:6379> set mykey a
OK
127.0.0.1:6379> APPEND mykey bbbb
(integer) 5
127.0.0.1:6379> get amykey
(nil)
127.0.0.1:6379> get mykey
"abbbb"

exists判断一个key是否存在 1表示存在 0表示不存在

127.0.0.1:6379> EXISTS mykey
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> get mykey
"abbbb"
127.0.0.1:6379> exists sss
(integer) 0

###########非常重要############################################
四、String 4
一:位运算
SDS => char[]   xxxx xxxx    char
                xxxx xxxx    char
                xxxx xxxx    char

1. 百雀林:500w左右的用户  => customerid  

   比如给某一批用户发送短信【营销】。。。 下午10点。。。  上午创建

   【交易金额大于50的,上海地区的,购买过某一个商品】

customerid,customerid,cutomerid,customerid。

table: customerid,customerid,cutomerid,customerid。  【300w】  Max:500w

        10,20,30,31,32,33,999,1222,......   【几百M】

        【customerid不重复】 我们customerid上限。


SDS => char[]   0000 0000    char
                0100 0000    char
                0001 0000    char

      char[375000]                        => 几M就搞定了。。。


C#: BitArray   [位数组]   
Redis位运算:

SETBIT key offset value  =>   String的value大小是512M   【数据传输太慢了】 【多而小的数据】

String的value大小是512M
static int checkStringLength(client *c, long long size) {
    if (size > 512*1024*1024) {
        addReplyError(c,"string exceeds maximum allowed size (512MB)");
        return C_ERR;
    }
    return C_OK;
}

01234567


char  => 从左到右   0000 0000   => offset = 7, set=1   => 0000 0001   => offset = 6, set=1   => 0000 0011

SDS => char[]   0000 0000    char
                0100 0000    char
                0001 0000    char
                。。。

customerid:10,20,


127.0.0.1:6379> SETBIT num 7 1
(integer) 0
127.0.0.1:6379> get num
"\x01"
127.0.0.1:6379> SETBIT num 6 1
(integer) 0
127.0.0.1:6379> get num
"\x03"

查看数量BITCOUNT
127.0.0.1:6379> SETBIT num 10 1
(integer) 0
127.0.0.1:6379> SETBIT num 20 1
(integer) 0
127.0.0.1:6379> BITCOUNT num
(integer) 4


GETBIT key offset

127.0.0.1:6379> GETBIT num 6
(integer) 1
127.0.0.1:6379> GETBIT num 7
(integer) 1
127.0.0.1:6379> GETBIT num 10
(integer) 1
127.0.0.1:6379> GETBIT num 5
(integer) 0
127.0.0.1:6379> GETBIT num 20
(integer) 1

BITCOUNT key [start end]  => 获取1的个数

BITOP operation destkey key [key ...]  => AND OR XOR NOT  [JAVA,C#]

对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

  0000  0001   => 1

& 0000  0010   => 2
--------------
  0000  0000   => 0

1 & 2 = 0


BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
BITOP NOT destkey srckey,对给定 key 求逻辑非,并将结果保存到 destkey


127.0.0.1:6379> setbit num1 7 1
(integer) 0
127.0.0.1:6379> setbit num2 6 1
(integer) 0
127.0.0.1:6379> get num1
"\x01"
127.0.0.1:6379> get num2
"\x02"
127.0.0.1:6379> bitop and num3 num1 num2
(integer) 1
127.0.0.1:6379> get num3
"\x00"
127.0.0.1:6379>

JS: BufferArray数组
###########非常重要#################################################################
(4)list双向结构
一:List  JAVA,C# 【Array】形式来实现的。。。
    双向链表,[单链表,单向循环链表,双向。。。十字链表]  
    [队列 和 栈]  queue,  stack
二:从源代码中了解List是如何构造的。。。


typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;


//迭代一个中间变量
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned long len;
} list;

为了方便对listNode进行管理,redis中使用list进行包装。。。
len:统计当前双向链表中的listnode的个数。。。 O(1)

list在redis中存放的形式:
redisObject

      type:    (0,1,2,3,4)  1
      encoding:
      ptr      

ptr => string   sds
prtr =>list      list -> listNode
RedisDb => Dict => key: redisObject    value:redisObject

ptr =>  list[双向链表]


/* Object types */
#define OBJ_STRING 0
#define OBJ_LIST 1
#define OBJ_SET 2
#define OBJ_ZSET 3
#define OBJ_HASH 4

时间复杂度都是:O(1)
LPUSH key value [value ...]  【redis做催付订单,卖家发货,签收提醒】
LPOP key
RPUSH key value [value ...]
RPOP key
LLEN key

例子LPUSH:
127.0.0.1:6379> LLEN mylist
(integer) 0
127.0.0.1:6379> lpush mylist "world"
(integer) 1
127.0.0.1:6379> LLEN mylist
(integer) 1
127.0.0.1:6379> lpush mylist "hello"
(integer) 2
127.0.0.1:6379> LLEN mylist
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"

#####RPOP用法
127.0.0.1:6379> lpush order "1001"
(integer) 1
127.0.0.1:6379> lpush order "1002"
(integer) 2
127.0.0.1:6379> lpush order "1003"
(integer) 3
127.0.0.1:6379> LRANGE order 0 -1
1) "1003"
2) "1002"
3) "1001"
127.0.0.1:6379> rpop order
"1001"
127.0.0.1:6379> LRANGE order 0 -1
1) "1003"
2) "1002"
127.0.0.1:6379>

client     redis:list      server

orderid:  1001
orderid:  1002
orderid:  1003

一:list 阻塞版本

client  ->   list    -> server

while(true){
try{
   var info= list.Rpop();

   ....process....
}
catch{

}
finally{
Thread.Sleep(1000);
}

}

没有数据的情况下,我们还是一直的轮询redis。。。

while(true){
try{
   var info= list.BRpop();   => 阻塞

   ....process....
}
catch{

}
finally{
Thread.Sleep(1000);
}

}

BRpop,BLpop  两种方式
BRPOP key [key ...] timeout 【s为单位】   

timeout: 0 表示永远等待 【connection被阻塞】
timeout:10 表示10s过期
MSMQ,RabbitMQ 都有这种等待。。。

例子:
127.0.0.1:6379> rpush orders 1001
(integer) 1
127.0.0.1:6379> rpush orders 1002
(integer) 2
127.0.0.1:6379> rpush orders 1003
(integer) 3
127.0.0.1:6379> rpush orders 1004
(integer) 4
127.0.0.1:6379> rpush orders 1005
(integer) 5

现象
127.0.0.1:6379> BRPOP orders 0
1) "orders"
2) "1004"
127.0.0.1:6379> BRPOP orders 0
1) "orders"
2) "1003"
127.0.0.1:6379> BRPOP orders 0
1) "orders"
2) "1002"
127.0.0.1:6379> BRPOP orders 0
1) "orders"
2) "1001"
127.0.0.1:6379> BRPOP orders 0
.......
这里在等待,阻塞

因为 BRPOP 和 BLPOP 基本是完全一样的,除了它们一个是从尾部弹出元素,而另一个是从头部弹出元素。

将当前的key和 timeout给了client struct。。。
    c->bpop.timeout = timeout;
    c->bpop.target = target;

在生产环境中使用的比较多的。。。

二:工具函数

LINDEX key index  获取index位置的数组。。。O(N)

  if (quicklistIndex(o->ptr, index, &entry))

head -> tail 进行遍历


127.0.0.1:6379> lindex orders 2
"10001"
127.0.0.1:6379> lrange orders 0 5
1) "10007"
2) "10008"
3) "10001"
4) "10002"
5) "10003"
127.0.0.1:6379>

LRANGE key start stop   O(N+M)


LINDEX用法:(生产环境少用,因为数据不断变化)
127.0.0.1:6379> lpush a 1
(integer) 1
127.0.0.1:6379> lpush a 2
(integer) 2
127.0.0.1:6379> lpush a 3
(integer) 3
127.0.0.1:6379> lpush a 4
(integer) 4
127.0.0.1:6379> LINDEX a 0
"4"
127.0.0.1:6379> LINDEX a -1
"1"


start: 可以是+,-  
stop :结束
js: substr

LRANGE key start stop  O(N)

redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> LRANGE mylist 0 0
1) "one"
redis> LRANGE mylist -3 2
1) "one"
2) "two"
3) "three"

LINSERT key BEFORE|AFTER pivot value

value插入到pivot之前还是之后。。。

LSET key index value   => 找index需要时间的。。。

(5)hash结构
一:Hash    Map, Dictionry
键值对  Array 关联数组
redis ,c语言中没有这种结构,,,redis自己实现了一个。。。

hash函数:
k,v   => 映射到数组中 Array
index = gethashcode( k) % array.length   
array[index]=[k,v];

HSET key field value

key: reidsObject  ptr->sds

value:redisObject ptr->dict =[key=field,vaue=value]

Dic => Dic [key:redisObject ptr=>SDS  value:redisObject ptr=>SDS]

例子#
127.0.0.1:6379> hset persons username "jack"
(integer) 1
127.0.0.1:6379> hset persons password "123456"
(integer) 1
127.0.0.1:6379> hget persons username
"jack"
127.0.0.1:6379> hget persons password
"123456"
127.0.0.1:6379>

int hashTypeSet(robj *o, robj *field, robj *value) {}
Map,HashTable  原理都是一样的。。。

一:hash其他的命令

1. 催付规则    [商品价格>30 ,上海地区的,不是黑名单用户,购买过某个商品]

   符合就发催付。。。

   联合利华:
   施华蔻:
   都市大药房旗舰店: 【商品维度】
  hash:

      shopid    regularID  regularEntity   ID=1
                regularID  regularEntity   ID=2

trade:  hgetall  获取所有的hash表内容 【共享内存】  ,避免每次来trade都要读取mysql


2. 分库分表:【shopid 都有一个DB】
hash:
       shopalloc
                   shopid   dbconnection
                   shopid   dbconnection
                                  
3. 策略使用 【复杂均衡】   hget,hkeys,hvals
                                                        logicserver

          client  ->  sellernick    ->   router         logicserver

                                                        logicserver

hash:  routeralloc   
                   sellernick logicserverIP
                   sellernick logicserverIP


Monitor => 用于给指定的sellernick分配logicserver   

db中的sellernickList 和 redis中的sellernickList进行比较。。。。

从redis中一次性把所有的sellernick捞出来,,, hkeys


HGETALL key  获取hash中的所有数据

127.0.0.1:6379> hset shopid_1 regularID_1 entity
(integer) 1
127.0.0.1:6379> hset shopid_1 regularID_2 entity2
(integer) 1
127.0.0.1:6379> hset shopid_1 regularID_3 entity3
(integer) 1
127.0.0.1:6379> hgetAll shopid_1
1) "regularID_1"
2) "entity"
3) "regularID_2"
4) "entity2"
5) "regularID_3"
6) "entity3"
127.0.0.1:6379>

例子:
127.0.0.1:6379> hset persons username "jack"
(integer) 1
127.0.0.1:6379> hset persons password "123456"
(integer) 1
127.0.0.1:6379> hget persons username
"jack"
127.0.0.1:6379> hget persons password
"123456"
127.0.0.1:6379> HGETALL persons
1) "username"
2) "jack"
3) "password"
4) "123456"

4. 短信通道

                  sellernick  channel1
                  sellernick  channel2


HDEL key field [field ...]    用于删除hash表。。。

HEXISTS key field             O(1)

hash:用于定值查找,时间复杂度永远都是O(1)   => hashfunction


127.0.0.1:6379> hset shopalloc 1 www.baidu.com
(integer) 1
127.0.0.1:6379> hset shopalloc 2 www.google.com
(integer) 1
127.0.0.1:6379> hlen shopalloc
(integer) 2
127.0.0.1:6379> hexists shopalloc 1
(integer) 1
127.0.0.1:6379> hexists shopalloc 1
(integer) 1
127.0.0.1:6379> hexists shopalloc 2
(integer) 1
127.0.0.1:6379> hexists shopalloc 3
(integer) 0
127.0.0.1:6379> hexists shopalloc 3


HINCRBY key field increment  

对field中的value进行递增,递增的值就是increment。。。。    String: incr


HKEYS key 所有hashtable中的所有keys。。。

127.0.0.1:6379> hkeys shopalloc
1) "1"
2) "2"

127.0.0.1:6379> hvals shopalloc
1) "www.baidu.com"
2) "www.google.com"


HLEN key

HMSET key field value [field value ...]  批量的执行mset。。。 通过一次tcp操作全部塞入到key中。。。

HSETNX key field value 【NX】 =>  【Not Exists】   做分布式锁【轻量级】

HSTRLEN key field 获取field中的value的长度

127.0.0.1:6379> hstrlen shopalloc 1
(integer) 13
127.0.0.1:6379> hstrlen shopalloc 2
(integer) 14

(5)set结构
一:Set
Set => 没有value的Hash

hash

     k, v


Set                  【空间要节省的多】
     k

二:应用场景 用户画像
ShopID: 旗舰店下面

Trade

商品维度:
productid_1: customerid,customerid ...........    Set
productid_2: customerid,customerid .......         Set


交易维度
customerid_1: 总交易金额,平均交易金额

地区维度:

shanghai: customerid,customerid.....         Set
beijing:  customerid,customerid....                 Set


购买 “洗发水” 上海地区的。。。     【关联推荐】
“洗发水”的productid:   看一下集合中是否有命中该customerid  O(1)
“上海” areaid:     看一下集合中是否包含。。。
如果两项都命中,那么我们直接发送“推荐”的彩信和邮件。。。。h5。
1. query,我们基本上做到了O(1)  cluster集群

2. maintain 维护


二:常见命令

1. SADD      
   SADD key member [member ...]     单个或者批量添加,节省的是我们tcp的传输量。。。

2. SISMEMBER  
   SISMEMBER key member   用于判断制定的member是否是set中的成员。。。


旗舰店基本上商品数都在1w之内。。。。 遍历1w次redis耗费的时候也就在5s内。。。。 【局域网】

例子
127.0.0.1:6379> sadd product_2 11 21 31 41
(integer) 4
127.0.0.1:6379> SMEMBERS product_2
1) "11"
2) "21"
3) "31"
4) "41"
127.0.0.1:6379> SISMEMBER product_2 11
(integer) 1
127.0.0.1:6379>


3.交集,差集,并集
交集: SINTER key [key ...]   后面都是要比较的key
并集: SUNION key [key ...]
差集: SDIFF key [key ...]

4. SCARD key  获取Set的元素个数

5. SPOP key [count] 随机弹出一个元素并且移除。。
   Removes and returns one or more random elements from the set value store at key.

6. SMEMBERS key  【查看所有的成员数据】

共享内存,强大的redis set集合。。。

(6)sorted set 结构

一:SortedSet   Java,C# 【SortDictinory 有序字典=> 红黑树(很复杂一种树结构,减少旋转)】
redis:skiplist 【跳跃表】 90年   【链表 来达到树的一个效果】  AVL,RedBlackTree  

严格的Log2N复杂度。。。  

1. 如何更快的时间,经过更少的城市达到目标城市

《1》到达北京: 直接飞机 一站达到  O(1)

《2》天津:     四个节点到天津。


【层次链表】 达到均摊的log2N 的时间复杂度。。。


2. 添加数据到sortedset中。。。。

《1》 优先级队列

《2》 top10的操作 【top N 大根堆,小根堆】

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

k:score      【权重,优先级】
v:member


127.0.0.1:6379> zadd trades 10 trade_10
(integer) 1
127.0.0.1:6379> zadd trades 20 trade_20
(integer) 1
127.0.0.1:6379> zadd trades 30 trade_30
(integer) 1
127.0.0.1:6379> zadd trades 40 trade_40
(integer) 1
127.0.0.1:6379> zadd trades 50 trade_50
(integer) 1
127.0.0.1:6379>


1.如果获取所有的数据

127.0.0.1:6379> zrange trades 0 -1    【从小到大的排序】
1) "trade_10"
2) "trade_20"
3) "trade_30"
4) "trade_40"
5) "trade_50"
127.0.0.1:6379>

###反向
127.0.0.1:6379> zrevrange trades 0 -1
1) "trade_50"
2) "trade_40"
3) "trade_30"
4) "trade_20"
5) "trade_10"


127.0.0.1:6379> zrange trades 0 -1 withscores
1) "trade_10"
2) "10"
3) "trade_20"
4) "20"
5) "trade_30"
6) "30"
7) "trade_40"
8) "40"
9) "trade_50"
10) "50"
127.0.0.1:6379>

ZREVRANGE key start stop [WITHSCORES] 根据

优先级队列:

1. 先获取最大值:

127.0.0.1:6379> zrevrange trades 0 0
1) "trade_50"

2. 删除最大值

127.0.0.1:6379> zremrangebyrank trades -1 -1
(integer) 1

127.0.0.1:6379> zrevrange trades 0 -1
1) "trade_50"
2) "trade_40"
3) "trade_30"
4) "trade_20"
5) "trade_10"
127.0.0.1:6379> zrevrange trades 0 0
1) "trade_50"
127.0.0.1:6379> zremrangebyrank trades -1 -1
(integer) 1
127.0.0.1:6379> zrevrange trades 0 -1
1) "trade_40"
2) "trade_30"
3) "trade_20"
4) "trade_10"
127.0.0.1:6379>

一般来说做两次操作。。。 【redis】 做优先级队列面临的一些问题。。。
Rabbitmq 专业级别的MQ产品。

(7)HyperLogLog
一:hyperloglog  【算法】

1. distinct + count


我们计算某一台的独立ip。。。。


《1》 使用set来保存某一天的所有ip数字。。。

  set  2016-12-26    192.168.10.121 192.168.10.122 192.168.10.123  192.168.10.121

       独立IP是多少呢?  3个。。。

       这时候,如果ip有1kw。。1ww。。。  【耗费巨大的内存】


《2》 hyperloglog 需要解决这种问题。。。

      1. 节省内存 每个HyperLogLog结构需要12K字节再加上key本身的几个字节  

                 hyperloglog + len(key)   最多也就是几十k。。。
                                          能够解决别人几百M所能解决的问题。。。
                hyperloglog不存储value,只是计算基数值。。。

      pfadd:   PFADD key element [element ...]

      pfcount: PFCOUNT key [key ...]

      pfmerge:

      2. 弊端:  有一定的错误率。。。   用错误率换取空间。。。  0.81% 。。。


二:Sort 【一个排序】 对key进行操作的。。
SORT key [BY pattern] [LIMIT offset count] [GET pattern] [ASC|DESC] [ALPHA] destination
更适合的去模仿sql。。。

如何让redis 模仿sql的一些语法
1. 直接sort key

sort uid

127.0.0.1:6379> sort uid
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sort uid desc
1) "3"
2) "2"
3) "1"
127.0.0.1:6379>

2. sort limit

select uid from users limit 0 1 desc

127.0.0.1:6379> sort uid limit 0 1 desc
1) "3"
127.0.0.1:6379> sort udi limit 0 1 asc
(empty list or set)
127.0.0.1:6379> sort uid limit 0 1 asc
1) "1"


3. sort [BY pattern]

uid  username_{0}  age_{1}

1    jack          30

2    mary          15

3    john          20

select usename from users order by age desc

jack
john
mary

上面这种场景该如何实现???


127.0.0.1:6379> sort uid by age_* get username_* desc
1) "jack"
2) "john"
3) "mary"

4. 我在获取usename的时候,想把uid也捞出来。。。
select uid,username from users order by age desc。。。
sort uid by age_* get username_* get #  desc


5. 获取所有。。。

select uid,username,age from users order by age desc....

127.0.0.1:6379> sort uid by age_* get username_* get # get age_*  desc
1) "jack"
2) "1"
3) "30"


127.0.0.1:6379>  HMSET user_info_1 name admin level 9999
OK
127.0.0.1:6379> HMSET user_info_2 name jack level 10
OK
127.0.0.1:6379>  HMSET user_info_3 name peter level 25
OK
127.0.0.1:6379>  HMSET user_info_4 name mary level 70
OK
127.0.0.1:6379> sort uid
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> rpush uid 4
(integer) 4
127.0.0.1:6379> sort uid
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> sort uid by user_info_*->level get user_info_*->name
1) "jack"
2) "peter"
3) "mary"
4) "admin"
127.0.0.1:6379> sort uid by user_info_*->level get user_info_*->name  desc
1) "admin"
2) "mary"
3) "peter"
4) "jack"
127.0.0.1:6379>
4) "john"
5) "3"
6) "20"
7) "mary"
8) "2"
9) "15"
127.0.0.1:6379>

复杂度不低的。。而且能不用就不用。。。毕竟以性能为代价。。。
(8)transaction事务
一:transaction

mysql,sqlserver。。。【复杂的机制】

nosql:为了保持简洁性,或多或少的砍掉了一些transaction的一些特性。。。弱化。。。

<1> create

<2> commit

<3> rollback

multi

xxxxxxx

exec 【提交】

discard 【取消】

watch,unwatch 【监测或者取消】

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set useranme jack
QUEUED
127.0.0.1:6379> set password 12345
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> keys *
1) "password"
2) "useranme"
127.0.0.1:6379>


127.0.0.1:6379> multi
OK
127.0.0.1:6379> set username jack
QUEUED
127.0.0.1:6379> set password 123456
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>

二:watch
mysql,sqlserver。。

watch num
multi  【在事务执行的过程中,我不希望被别人修改】
incr num   【0,1  ,2】  本来你想从0 -> 1  结果,看到的效果就是 0 -> 2 了。。。
exec [discard]

multi

incr num

exec  【取消】

client incr num  

《1》不用watch

incr :生成订单号。。。。   discard。。。
watch的本意就是要保证在mutli的过程中,数据必须是干净的。。。。

redisDb中有一个watched_keys
(9)pub与sub
一:发布订阅模式
1. 观察者模式 【设计模式中的一种】  .net  WPF 中就有一种MVVM模式。。
                                    js    knockoutjs mvvm模式。。。
                 subject

subscribe  subcribe  subcribe  subcribe

SUBSCRIBE channel [channel ...]

channel:就是subject 【频道】    收音机


PUBLISH channel message   用于更新。。。

##发送端
127.0.0.1:6379> PUBLISH 188.12 "hello"
(integer) 1
127.0.0.1:6379> PUBLISH new.* "hello"
(integer) 1
127.0.0.1:6379>

##接受端1
127.0.0.1:6379> subscribe new.*
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "new.*"
3) (integer) 1
1) "message"
2) "new.*"
3) "hello"

##接受端2
127.0.0.1:6379> SUBSCRIBE 188.12
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "188.12"
3) (integer) 1
1) "message"
2) "188.12"
3) "hello"

直接订阅特定的频道,一对一的关系。。。

如果订阅一个类别。。。 【模式匹配】  new.*   => new.it  or  new.sport

*:正则字符

PSUBSCRIBE pattern [pattern ...]  => p[pattern] 模式。。。

MQ: Rabbitmq   【发布订阅模式】

client ->  mq  ->  server     【长连接】

[iyunv@localhost Desktop]# redis-cli
127.0.0.1:6379> subscribe 188.12
Reading messages... (press Ctrl-C to quit)

127.0.0.1:6379> psubscribe news.*
Reading messages... (press Ctrl-C to quit)


如果client端推送大量的消息,,, 1s  100

这时候server并不能快速的处理,,,, logic process..... 而且读取db,soa webapi...  

这时候server不能及时处理,导致大量积压。。。 【1:memory挂掉。。。
                                               2:cpu 100%   
                                               3:容易丢失消息[server挂掉]】
二:源码 [RedisClient]

1. 非模式       dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */   字典
       
                  key           value
                subject1        client1 -> client2  -> client3  -> client4

                subject2        client1 -> client9  

publish subject1 helloworld   所以查找key的复杂度是O(1)

2. 模式         list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */   链表
                pubsubPattern   ->  pubsubPattern           
                     c1                  c3
                pattern= news.*    pattern= trip.*

使用redis,定义的模式匹配的频道不会特别多。。。肯定不会超过100个。。。  遍历的复杂度O(N)
(9)过期键EXPIRE
一:过期键
1. redis 作为Cache使用。。。
set username jack  ....[ms] [ms]

2.第一种,初始化设置。。。  set
  第二种:后期更改
  第三种:过期变成持久。。。

SET key value [EX seconds] [PX milliseconds] [NX|XX]

1、EXPIRE key seconds  将一个key变为过期键。。。   【以s为单位】
2、PEXPIRE key milliseconds  将一个key变成过期键, 【以ms为单位】

3、以某一个时间点为过期键,比如说,2016-12-27 9:07   想 2016-12-27 10:00 过期。。。。
EXPIREAT key timestamp  

127.0.0.1:6379> set a a
OK
127.0.0.1:6379> EXPIRE a 10
(integer) 1
127.0.0.1:6379> ttl a
(integer) 7
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> ttl a
(integer) -2


Cache  

redis作为一个Cache。。。   memcache 真的是一样的。。。

# maxmemory <bytes>   设置最大的内存  byte为单位。。。

server:100M

maxmemory: 50M


如果数据大于50M我该怎么办???

# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations


lru => leaset recently used  【最久未使用的】

volatile-lru:  从过期键中去找最久未使用的数据。。。

allkeys-lru:    从所有的keys中通过lru算法去删除。。。

volatile-ttl:  redisObject  找到马上要过期的lru时间  

# maxmemory-policy noeviction

redis监控  
[iyunv@node1 ~]# redis-cli --stat
------- data ------ --------------------- load -------------------- - child -
keys       mem      clients blocked requests            connections         
5          843.38K  3       0       52 (+0)             6           
5          843.38K  3       0       53 (+1)             6           
5          843.38K  3       0       54 (+1)             6           
5          843.38K  3       0       55 (+1)             6           
5          843.38K  3       0       56 (+1)             6           
5          843.38K  3       0       57 (+1)             6           
5          843.38K  3       0       58 (+1)             6           
5          843.38K  3       0       59 (+1)             6


(10)batchcommit性能优化
一:redis 两点性能优化。。。
1. 批量提交

<1> mset 。。。。 驱动,。。。。

   千人千面的时候,需要有一个数据初始化。。。
400w - 500w customerid

customerid_1  22

customerid_2  21

customerid_3  14

操作400w  - 500w  tcp链接。。。。 几个G。。。  【1h】

<2> mset

mset customerid_1 22  customerid_2  21  ....   

网络卡死 +  超时。。。。

1w条提交一次。。。

jedis来演示一下。
        public static void main(String[] args) {
                Jedis redis=new Jedis("192.168.23.155",6379);
               
//                String[] strlist={"customerid_1","22","customerid_2","21","customerid_3","14"};
               
                ArrayList<String> arrayList=new ArrayList<>();
               
                arrayList.add("customerid_1");
                arrayList.add("22");
               
                arrayList.add("customerid_2");
                arrayList.add("21");
               
                arrayList.add("customerid_3");
                arrayList.add("14");
               
                String[] strlist=new String[arrayList.size()];
               
            arrayList.toArray(strlist);
               
                redis.mset(strlist);   //batch
       
           System.out.println("success");
        }


2. 多命令
mset  string的批量
hmset hash的批量
sadd  set的批量


如果做到三种命令的混合呢???
set name jack
hset person name jack
sadd tags china

这样的三条混合命令,如果一次性提交???  【节省的网络的轮回】
pipeline 【管道】  redis。。。

jedis来实现。。。

package mytest2;
import java.util.ArrayList;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

public class Program {

        public static void main(String[] args) {
                Jedis redis=new Jedis("192.168.23.155",6379);
       
                //start pipeline
            Pipeline pipeline=redis.pipelined();
       
            pipeline.set("name","jack");
            pipeline.hset("person","name","mary");
            pipeline.sadd("tags", "china");
            
            pipeline.sync();   //execute....
            
           System.out.println("success");
        }
}

(11)lua脚本

(12)aof rdb 持久化
redis默认是rdb模式
一:redis序列化。
memcached 没有序列化。。。
1. rdb
   快照的模式。 mongodb。。。  【定点保存】如果重启会丢掉一些数据。。。。
    flush data to disk。。。
    redis默认就是rdb模式。。。
   触发机制:  
   save time changes

save 900 【15min】 1
save 300 【3min】 10
save 60 【1min】 10000

在Redis中使用serverCron来实现这个检测。。。

定期检测 三个save是否满足,如果满足,调用bgsave。。。


手工进行save,bgsave 保存。。。

######非常重要#########################################
save:同步保存,保存期间,client是被阻塞的。。。  #####
                                                  #####
int rdbSave(char *filename);                      #####
                                                  #####
bgsave:  开启子进程来保存。。。                  #####
                                                  #####
#######################################################

2. aof  
来一条命令,保存一次。。。。 aof文件是保存我们的 。。。文本协议。。。
默认是不启用的。
如果开启:
1. appendonly yes

# appendfsync always     => 来一条保存一条。。 强制的执行fsync命令。。。  告诉操作系统强制flush到disk。    【slow,safe】 最多丢失一条数据

appendfsync everysec     => 1秒 flush 一次。。。。  fsync命令  【折中】 最多丢失1s数据

# appendfsync no         => flush。。。           fsync命令。。等待操作系统将自己缓冲区中的数据flush到硬盘。。。  【unsafe】  不知道。。。


=> select 0   

=>  set username  jack

=>  set password 12345


         /* Trigger an AOF rewrite if needed */
         if (server.rdb_child_pid == -1 &&
             server.aof_child_pid == -1 &&
             server.aof_rewrite_perc &&
             server.aof_current_size > server.aof_rewrite_min_size)
         {
            long long base = server.aof_rewrite_base_size ?
                            server.aof_rewrite_base_size : 1;
            long long growth = (server.aof_current_size*100/base) - 100;
            if (growth >= server.aof_rewrite_perc) {
                serverLog(LL_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
                rewriteAppendOnlyFileBackground();
            }
         }

rewriteAppend:   如果db暴涨。。。redis命令是不是特别多。。。

CURD操作。。。

set username jack

set username mary

set username peter

set username asdfasdf


如果对username进行了100w操作。。。那命令多的吓人。。。

所以redis做了一个机制,如果达到某一个阈值,会进行rewrite

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

1. 如果你的文件有128M。。。   64 x 2 = 128

生成快照 -> 生成命令到aof文件中。。。【缩小了文件的尺寸】


(13)master - slave
一:redis:多机操作
master - slave
1. 数据的热备份
   如果master宕机了,slave还是有完整的备份。。。。 【热备份】
2. 分解读写压力
   如果你的业务读写特别大。。。 【分流】
   分而治之。。。
一般来说, 读写8:2   10个操作中有8个读,2个写。。。
这时候,就有一个集群来抗读写操作。。。

3. 可以在slave上做冷备份
   防止程序员,运维的误操作。。。比如说我做了flushall的操作。。。
   直接copy一个slave3 的rdb文件。。。
mysql,sqlserver中 master - slave 概念
nosql:基本上都有。。。

二:实践
用3台 Centos去做
centos1: 192.168.23.158   master
centos2: 192.168.23.152   slave1
centos3: 192.168.23.145   slave2

######################

配置非常简单,只要在从库设置如下内容即可 设置主库的ip及端口即可
slaveof <masterip> <masterport>

(1)master主要配置如下:
#bind 127.0.0.1
protected-mode no
port 6379
#其他不用配置也可以

(2)slave1配置如下:
#bind 127.0.0.1
protected-mode no
port 6379
slaveof 192.168.175.29 6379
(3)salve2配置如下
#bind 127.0.0.1
protected-mode no
port 6379
slaveof 192.168.175.29 6379

注意:这里具体的ip看你自己的了哦!!!!!

redis-cli slaveof 命令

修改配置文件 slaveof命令。。。

# masterauth <master-password>   如果master有密码,可以在这里配置。。。

3257:M 28 Dec 06:28:53.339 * Slave 192.168.23.152:6379 asks for synchronization
3257:M 28 Dec 06:28:53.339 * Full resync requested by slave 192.168.23.152:6379
3257:M 28 Dec 06:28:53.339 * Starting BGSAVE for SYNC with target: disk
3257:M 28 Dec 06:28:53.340 * Background saving started by pid 3376
3376:C 28 Dec 06:28:53.349 * DB saved on disk
3376:C 28 Dec 06:28:53.350 * RDB: 6 MB of memory used by copy-on-write
3257:M 28 Dec 06:28:53.445 * Background saving terminated with success
3257:M 28 Dec 06:28:53.446 * Synchronization with slave 192.168.23.152:6379 succeeded


三:验证

# Replication
role:master
connected_slaves:2
slave0:ip=192.168.23.152,port=6379,state=online,offset=127,lag=0
slave1:ip=192.168.23.145,port=6379,state=online,offset=141,lag=0
master_repl_offset:141
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:140


# Keyspace
127.0.0.1:6379> info Replication
# Replication
role:slave
master_host:192.168.23.158
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:211
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379>

四:落地实践
1.redis-cli
通过验证,没有问题。。。
2. C# client  =>  master - slave。。。。
        static void Main(string[] args)
        {
            //创建链接
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.23.158:6379,192.168.23.152:6379,192.168.23.145:6379");

            //获取db
            var database = redis.GetDatabase();

            //database.StringSet("username", "hellworld");

            var str = database.StringGet("username");
        }

(14)sentinel【哨兵】
一:sentinel  【哨兵】
master -> slave
如果master挂掉了,,,程序只能读取,不能写入了。。。

info:命令获取master集群的所有信息,比如说 slave的ip地址等信息。。。。

主观: 个人的想法 【不一定真的下线】

客观: 基本事实   【如果有某几个人都说master挂掉了,才是事实】

二:搭建
1. centos-1  192.168.23.158    master      
2. centos-2  192.168.23.152    slave1
3. centos-3  192.168.23.145    slave2
4. centos-4  192.168.23.154  放三台 sentinel。。。。

《1》 sentinel:
port
monitor masterhost masterip
客观下线: quorum  [阈值]
主观下线: 下线的标准 【】 15s,30s。1min。。。
其余的采用默认配置。。。

sentinel auth-pass <master-name> <password>   =》 master 有密码,在这地方设置。。。
sentinel monitor <master-name> <ip> <redis-port> <quorum>
port 26379
sentinel down-after-milliseconds mymaster 30000

protected-mode no  一定要关掉

高可用的模式。。。你可以down 掉任何一台机器。。。sentinel会给我们重新选举select。。。

C#,Java连接一下。。。  塞几个ip地址就ok了。。。

一主2从搭建我就不说了

下面说一下
sentinel.conf

只要配置如下内容
(1)配置文件1
protected-mode no
port 26382
sentinel monitor mymaster 192.168.23.158 6379 2

(2)配置文件12
protected-mode no
port 26383
sentinel monitor mymaster 192.168.23.158 6379 2

(3)配置文件12
protected-mode no
port 26384
sentinel monitor mymaster 192.168.23.158 6379 2

分别在3台机器启动:
./redis-sentinel  sentinel.conf
./redis-sentinel  sentinel.conf
./redis-sentinel  sentinel.conf


ps -ef | grep  redis
当kill -9 master进程
然后启动redis server时
以前的master角色变成了slave角色
sentinel【哨兵】从2个slave当中选一个当做master角色

具体日志信息如下:

10294:X 08 Mar 03:33:24.533 # +sdown master mymaster 192.168.175.29 6379
10294:X 08 Mar 03:33:24.605 # +odown master mymaster 192.168.175.29 6379 #quorum 3/2
10294:X 08 Mar 03:33:24.605 # +new-epoch 1
10294:X 08 Mar 03:33:24.605 # +try-failover master mymaster 192.168.175.29 6379
10294:X 08 Mar 03:33:24.624 # +vote-for-leader 3da9f7fdfda091e1d443fd5bbd8d77f3ac312016 1
10294:X 08 Mar 03:33:24.624 # 38e1ed45641a1479dece7f06105be01246e694e1 voted for 38e1ed45641a1479dece7f06105be01246e694e1 1
10294:X 08 Mar 03:33:24.633 # 1449d4f234e10a642c1155a68412e4ce529ba92f voted for 38e1ed45641a1479dece7f06105be01246e694e1 1
10294:X 08 Mar 03:33:25.223 # +config-update-from sentinel 38e1ed45641a1479dece7f06105be01246e694e1 192.168.175.29 26384 @ mymaster 192.168.175.29 6379
10294:X 08 Mar 03:33:25.223 # +switch-master mymaster 192.168.175.29 6379 192.168.175.29 6381
10294:X 08 Mar 03:33:25.223 * +slave slave 192.168.175.29:6380 192.168.175.29 6380 @ mymaster 192.168.175.29 6381
10294:X 08 Mar 03:33:25.223 * +slave slave 192.168.175.29:6379 192.168.175.29 6379 @ mymaster 192.168.175.29 6381
10294:X 08 Mar 03:33:55.268 # +sdown slave 192.168.175.29:6379 192.168.175.29 6379 @ mymaster 192.168.175.29 6381


这里的ip看你自己的ip   

(15)redis监控
一:redis的监控 【可视化的工具】
学习连接
http://www.cnblogs.com/huangxinc ... /06/08/5571185.html


winform
web
1. 程序员要经常用到的一个可视化监控工具。。。。
   mysql,sqlserver 都有一个可视化界面。。。
Redis Desktop Manager

Redis Client   【国人开发】  https://github.com/caoxinyu/RedisClient
<a href="https://raw.githubusercontent.com/caoxinyu/RedisClient/windows/release/redisclient-win32.x86.2.0.exe">redisclient-win32.x86.2.0.exe</a>
有了可视化工具,就不用每次都输入命令去查看。。。

Redis Studio


二:web监控。。【redislive】
github 源码地址如下:
https://github.com/nkrode/RedisLive

http://www.cnblogs.com/huangxinc ... /06/08/5571185.html
python 写的一个web监控。。。
1. 安装pip =>  python的安装工具包。。。 C# nuge, java maven。。。



下载:https://pypi.python.org/pypi/pip

[iyunv@localhost Desktop]# python
Python 2.7.5 (default, Nov 20 2015, 02:00:19)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

2.python setup.py install  安装pip工具包
3.pip install tornado   python server :【java tomcat,.net IIS】
4. pip install redis    python redis驱动 【java jedis,.net StackExchange】
5. pip install python-dateutil --upgrade   # python dateutil类库。。。 【java 工具类jar】


6. 获取redislive的源代码  python的应用程序
RedisServers: 你需要监控的redis server。。。。
DataStoreType: RedisLive  【sqlite,redis】  专门开一台redis存放RedisLive的统计信息
RedisStatsServer: 统计信息存放的Redis地址。。。

7. 开启统计的redis
8. 开启监控脚本  ./redis-monitor.py --duration=120
9. 开启web站点   ./redis-live.py

1083  mkdir /usr/local/python27
1084  cd Python-2.7.5
1085  ll
1086  ./configure --prefix=/usr/local/python27
1087  make
1088  make install
1089  python
1090  mv /usr/bin/python /usr/bin/python2.6.6
1091  ln -s /usr/local/python27/bin/python /usr/bin/python

1132  tar zxvf setuptools-0.6c11.tar.gz
1133  cd setuptools-0.6c11
1134  python setup.py build
1135  python setup.py install
1136  cd ../pip-8.1.2
1137  python setup.py  build
1138  python setup.py  install


[iyunv@node1 soft]# find / -name python2.6
/usr/include/python2.6
/usr/lib64/python2.6
/usr/lib/python2.6
/usr/bin/python2.6

三:怎么实现的。。
RedisLive : monitor,info。。。。来构建一个趋势图。。。
Redis Live is a dashboard application with a number of useful widgets. At it's heart is a monitoring script that periodically issues INFO and MONITOR command to the redis instances and stores the data for analytics.
monitor.py 脚本。。。


我的配置文件如下:
[iyunv@node2 RedisLive-master]# vim src/redis-live.conf

{
        "RedisServers":
        [
                {
                        "server": "192.168.175.29",
                        "port" : 6379
                },

                {
                        "server": "192.168.175.29",
                        "port" : 6380
                },
                 {
                        "server": "192.168.175.29",
                        "port" : 6381
                }
        ],

        "DataStoreType" : "redis",

        "RedisStatsServer":
        {
                "server" : "192.168.175.30",
                "port" : 6379
        }
}


(16)redis3集群
一: redis cluster 3.0 出来的
1. 为什么集群:
   master -slave
   sentinel
如果我的数据有1T。。。那如何存放到redis中。。。
去重新化的方式
mongodb
              monogd
client       mongos    mongod
              mongod
中心化



redis: p2p的方法 【去重新化】
1. 首先redis集群使用16384个slot。。。

由三台机器承载16384个slot...
client -> hash(username)   

0< hash(username) < 16383
eg: hash(username)=100

                   redis
client   hash     redis
                   redis


这个hash(username)函数实在各自的client端。。。【驱动中内置的】

2. cluster 内置了sentinel + master/slave + partition...


3.

4台centos

  centos1:  192.168.23.158  
  centos2:  192.168.23.152
  centos3:  192.168.23.145
  centos4:  192.168.23.154     三台slave



三:操作步骤:

1. 开启cluster模式

cluster-enabled yes                    开启集群状态
cluster-config-file nodes-6379.conf    集群的节点文件
./redis-server ./redis.conf


2. 找到一个叫做 redis-trib.rb 的文件 rb=>  ruby
   centos 没有ruby的环境。。。
   安装一系列的依赖包。。。
//通过第三方工具进行安装
./redis-trib.rb create --replicas 1 192.168.23.158:6379 192.168.23.152:6379 192.168.23.145:6379 192.168.23.154:6379 192.168.23.154:6380 192.168.23.154:6381

《1》 ruby环境
《2》 ruby的redis驱动安装    gem install redis

[iyunv@localhost redis]# ./redis-trib.rb create --replicas 1 192.168.23.158:6379 192.168.23.152:6379 192.168.23.145:6379 192.168.23.154:6379 192.168.23.154:6380 192.168.23.154:6381
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.23.158:6379
192.168.23.152:6379
192.168.23.145:6379
Adding replica 192.168.23.154:6379 to 192.168.23.158:6379
Adding replica 192.168.23.154:6380 to 192.168.23.152:6379
Adding replica 192.168.23.154:6381 to 192.168.23.145:6379
M: cbfadb06673f7eb69483aa2031cb60fc4251fb7a 192.168.23.158:6379
   slots:0-5460 (5461 slots) master
M: 2160b439f59fafc3bb02fe920933284d5df3f39e 192.168.23.152:6379
   slots:5461-10922 (5462 slots) master
M: 38a05510f8014d7fdf7b9c606461ecaae5a47b2a 192.168.23.145:6379
   slots:10923-16383 (5461 slots) master
S: 2628c7fa7630d544b7d4a727d563a49c68578240 192.168.23.154:6379
   replicates cbfadb06673f7eb69483aa2031cb60fc4251fb7a
S: 30c4755c49b228af5e111baa74dbebb85c4185c8 192.168.23.154:6380
   replicates 2160b439f59fafc3bb02fe920933284d5df3f39e
S: 75a81dbaeb8d46b0783adb3ab8aeec405608ca18 192.168.23.154:6381
   replicates 38a05510f8014d7fdf7b9c606461ecaae5a47b2a
Can I set the above configuration? (type 'yes' to accept):


[iyunv@localhost s1]# ./redis-cli
127.0.0.1:6379> cluster nodes
2628c7fa7630d544b7d4a727d563a49c68578240 192.168.23.154:6379 myself,slave cbfadb06673f7eb69483aa2031cb60fc4251fb7a 0 0 4 connected
38a05510f8014d7fdf7b9c606461ecaae5a47b2a 192.168.23.145:6379 master - 0 1483019113842 3 connected 10923-16383
75a81dbaeb8d46b0783adb3ab8aeec405608ca18 192.168.23.154:6381 slave 38a05510f8014d7fdf7b9c606461ecaae5a47b2a 0 1483019115859 6 connected
30c4755c49b228af5e111baa74dbebb85c4185c8 192.168.23.154:6380 slave 2160b439f59fafc3bb02fe920933284d5df3f39e 0 1483019114335 5 connected
cbfadb06673f7eb69483aa2031cb60fc4251fb7a 192.168.23.158:6379 master - 0 1483019114840 1 connected 0-5460
2160b439f59fafc3bb02fe920933284d5df3f39e 192.168.23.152:6379 master - 0 1483019110809 2 connected 5461-10922
127.0.0.1:6379>

redis-cli做一个演示。。。  set username jack

root@localhost s1]# ./redis-cli -c
127.0.0.1:6379> set username jack
-> Redirected to slot [14315] located at 192.168.23.145:6379
OK
192.168.23.145:6379> set password 12345
-> Redirected to slot [9540] located at 192.168.23.152:6379
OK
192.168.23.152:6379> set email 3234234@qq.com
OK
192.168.23.152:6379>


总结:学到这里算入门了!其他看个人修行了!!





运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-354756-1-1.html 上篇帖子: Linux下redis源码安装 下篇帖子: python实现 redis订阅与发布
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表