码迷,mamicode.com
首页 > 其他好文 > 详细

redis入门到精通

时间:2017-03-23 21:02:27      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:redis入门到精通

redis入门到精通

redis3.2.8学习

  1. (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  命令持久化数据到磁盘


或者

[root@node1 redis]# redis-cli set id 1

OK

[root@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     【长连接】


[root@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监控  

[root@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/huangxincheng/archive/2016/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/huangxincheng/archive/2016/06/08/5571185.html

python 写的一个web监控。。。

1. 安装pip =>  python的安装工具包。。。 C# nuge, java maven。。。


 


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


[root@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

 

 

[root@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 脚本。。。



我的配置文件如下:

[root@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


[root@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): 



[root@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> 



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























本文出自 “梁小明的博客” 博客,请务必保留此出处http://7038006.blog.51cto.com/7028006/1909799

redis入门到精通

标签:redis入门到精通

原文地址:http://7038006.blog.51cto.com/7028006/1909799

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!