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

或者

[[email protected] redis]# redis-cli set id 1

OK

[[email protected] 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     【长连接】

[[email protected] 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监控

[[email protected] ~]# 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

[[email protected] 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

[[email protected] 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 脚本。。。

我的配置文件如下:

[[email protected] 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

[[email protected] 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):

[[email protected] 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

[email protected] 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 [email protected]

OK

192.168.23.152:6379>

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

时间: 2024-10-24 15:26:13

redis入门到精通的相关文章

redis 入门到精通

Redis :Remote Directory server 远程服务器字典 Redis官网 http://redis.io/

Redis从入门到精通:初级篇

原文链接:http://www.cnblogs.com/xrq730/p/8890896.html,转载请注明出处,谢谢 Redis从入门到精通:初级篇 平时陆陆续续看了不少Redis的文章了,工作中也一直在用Redis,感觉是时候对过往Redis的所学进行一次系统性的总结.<Redis从入门到精通>系列会分为初级.中级.高级三篇,从浅入深讲解Redis相关知识点. 在本文中,我们将看到以下内容: Redis简介 Redis安装.启动 Redis登录授权 Redis配置文件redis.conf

2017最新技术java高级架构、千万高并发、分布式集群、架构师入门到精通视频教程

* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat

Docker从入门到精通系列(1)---第一个web应用

本文为minimicall原创文章,转载需注明出处:http://blog.csdn.net/minimicall 在继<阿里云部署Docker>之后,我决定系统的出一系列<Docker从入门到精通>的深度记录文章,这源于有一天图灵出版社的一个编辑联系我,问我有没有兴趣写Docker方面的书籍进行出版. 本文的目标是建立一个Docker web app.这样,你就可以直观的感受,docker是如何部署一个web应用. 首先,我们建立一个空目录来存放我们需要的文件. 我们建立的是一个

Kali Linux安全渗透-从入门到精通

Kali-Linux是基于Debian Linux发行版 针对高级渗透测试和安全审计系统.带你一起从入门到精通. 什么是Kali-Linux? kali 包含几百个软件用来执行各种信息安全的任务,如渗透测试,取证和逆向工程的工具.Kali-Linux 由Offensive Security维护. 为什么要学Kali-Linux? 作为一名渗透测试人员,如果你不懂Kali-Linux那么你就真的OUT了!Kali-Linux作为最成功的渗透测试操作系统之一,他封装了数百种享誉盛名的渗透工具,那么不

区块链技术从入门到精通

详情请交流  QQ  709639943 01.区块链技术从入门到精通 02.2017年新生大学区块链视频教程 03.Node.js入门到企业Web开发中的应用 04.精通高级RxJava 2响应式编程思想 05.Java秒杀系统方案优化 高性能高并发实战 06.Java深入微服务原理改造房产销售平台 07.快速上手Linux 玩转典型应用 08.快速上手Ionic3 多平台开发企业级问答社区 09.Java Spring Security开发安全的REST服务 10.深入Java虚拟机(JVM

nginx教程从入门到精通

[转]nginx教程从入门到精通 nginx教程写了一段时间,无意中发现,nginx相关文章已经达到了近100篇了.觉得很有必要汇总到一起,它是我们运维生存时间的一片心血,他是学习nginx的同学必看教程- -!,我们将会继续更新内容,不过内容难免有错误,希望大家指正. Nginx基础 1.  nginx安装 2.  nginx 编译参数详解 3.  nginx安装配置+清缓存模块安装 4.  nginx+PHP 5.5 5.  nginx配置虚拟主机 6.  nginx location配置

《Spring Data JPA从入门到精通》内容简介、前言

内容简介 本书以Spring Boot为技术基础,从入门到精通,由浅入深地介绍Spring Data JPA的使用.有语法,有实践,有原理剖析. 本书分为12章,内容包括整体认识JPA.JPA基础查询方法.定义查询方法.注解式查询方法.@Entity实例里面常用注解详解.JpaRepository扩展详解.JPA的MVC扩展REST支持.DataSource的配置.乐观锁.SpEL表达式在Spring Data里面的应用.Spring Data Redis实现cacheable的实践.Intel

2018大数据学习路线从入门到精通

最近很多人问小编现在学习大数据这么多,他们都是如何学习的呢.很多初学者在萌生向大数据方向发展的想法之后,不免产生一些疑问,应该怎样入门?应该学习哪些技术?学习路线又是什么?今天小编特意为大家整理了一份大数据从入门到精通的学习路线.并且附带学习资料和视频.希望能够帮助到大家.大数据学习资料分享群:119599574 第一阶段:Linux理论 (1)Linux基础:(2)Linux-shell编程:(3)高并发:lvs负载均衡:(4)高可用&反向代理 第二阶段:Hadoop理论 (1)hadoop-