古城热线 发表于 2018-11-4 07:59:35

一步一步学习redis3.2.8

  一步一步学习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命令持久化数据到磁盘
  或者

  # redis-cli set>  OK

  # redis-cli get>  "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 结构
  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
  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单线程的内存字典服务器。。。 过期时间=》 kv结构。
  SET key value
  缓存,和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
  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
  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                        => 几M就搞定了。。。
  C#: BitArray   [位数组]
  Redis位运算:
  SETBIT key offset value=>   String的value大小是512M   【数据传输太慢了】 【多而小
  的数据】
  String的value大小是512M

  static int checkStringLength(client *c, long long>  if (size > 512*1024*1024) {

  addReplyError(c,"string exceeds maximum allowed>  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 => 获取1的个数
  BITOP operation destkey key => AND OR XOR NOT
  对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
  00000001   => 1
  & 00000010   => 2
  --------------
  00000000   => 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>
  4、list双向结构
  一:ListJAVA,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 【redis做催付订单,卖家发货,签收提醒】
  LPOP key
  RPUSH key 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 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 stopO(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结构
  1. 催付规则    [商品价格>30 ,上海地区的,不是黑名单用户,购买过某个商品]
  符合就发催付。。。
  联合利华:
  施华蔻:
  都市大药房旗舰店: 【商品维度】
  hash:

  shopid    regularIDregularEntity>
  regularIDregularEntity>  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. 短信通道
  sellernickchannel1
  sellernickchannel2
  HDEL key 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 批量的执行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
  6、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:   看一下集合中是否有命中该customeridO(1)
  “上海” areaid:   看一下集合中是否包含。。。
  如果两项都命中,那么我们直接发送“推荐”的彩信和邮件。。。。h5。
  1. query,我们基本上做到了O(1)cluster集群
  2. maintain 维护
  二:常见命令
  1. SADD
  SADD key 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
  并集: SUNION key
  差集: SDIFF key
  4. SCARD key获取Set的元素个数
  5. SPOP key 随机弹出一个元素并且移除。。
  Removes and returns one or more random elements from the set value store at key.
  6. SMEMBERS key【查看所有的成员数据】
  共享内存,强大的redis set集合。。。
  7、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 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 根据
  优先级队列:
  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产品。
  8、HyperLogLog
  一:hyperloglog【算法】
  1. distinct + count
  我们计算某一台的独立ip。。。。
  《1》 使用set来保存某一天的所有ip数字。。。
  set2016-12-26    192.168.10.121 192.168.10.122 192.168.10.123192.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
  pfcount: PFCOUNT key
  pfmerge:
  2. 弊端:有一定的错误率。。。   用错误率换取空间。。。0.81% 。。。
  二:Sort 【一个排序】 对key进行操作的。。
  SORT key
  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
  uidusername_{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_*->namedesc
  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>
  复杂度不低的。。而且能不用就不用。。。毕竟以性能为代价。。。
  9、transaction事务
  一:transaction
  mysql,sqlserver。。。【复杂的机制】
  nosql:为了保持简洁性,或多或少的砍掉了一些transaction的一些特性。。。弱化。。。
   create
   commit
   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
  multi
  incr num
  exec【取消】
  client incr num
  《1》不用watch
  incr :生成订单号。。。。   discard。。。
  watch的本意就是要保证在mutli的过程中,数据必须是干净的。。。。
  redisDb中有一个watched_keys
  10、pub与sub
  一:发布订阅模式
  1. 观察者模式 【设计模式中的一种】.netWPF 中就有一种MVVM模式。。
  js    knockoutjs mvvm模式。。。
  subject
  subscribesubcribesubcribesubcribe
  SUBSCRIBE 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.itornew.sport
  *:正则字符
  PSUBSCRIBE pattern => p 模式。。。
  MQ: Rabbitmq   【发布订阅模式】
  client ->mq->server   【长连接】
  # 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端推送大量的消息,,, 1s100
  这时候server并不能快速的处理,,,, logic process..... 而且读取db,soa webapi...
  这时候server不能及时处理,导致大量积压。。。 【1:memory挂掉。。。
  2:cpu 100%
  3:容易丢失消息】
  二:源码
  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)
  11、过期键EXPIRE
  1. redis 作为Cache使用。。。
  set username jack....
  2.第一种,初始化设置。。。set
  第二种:后期更改
  第三种:过期变成持久。。。
  SET key value
  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    设置最大的内存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监控
  # redis-cli --stat
  ------- data ------ --------------------- load -------------------- - child -
  keys       mem      clients blocked requests            connections
  5          843.38K3       0       52 (+0)             6
  5          843.38K3       0       53 (+1)             6
  5          843.38K3       0       54 (+1)             6
  5          843.38K3       0       55 (+1)             6
  5          843.38K3       0       56 (+1)             6
  5          843.38K3       0       57 (+1)             6
  5          843.38K3       0       58 (+1)             6
  5          843.38K3       0       59 (+1)             6
  12、batchcommit性能优化
  一:redis 两点性能优化。。。
  1. 批量提交
   mset 。。。。 驱动,。。。。
  千人千面的时候,需要有一个数据初始化。。。
  400w - 500w customerid
  customerid_122
  customerid_221
  customerid_314
  操作400w- 500wtcp链接。。。。 几个G。。。【1h】
   mset
  mset customerid_1 22customerid_221....
  网络卡死 +超时。。。。
  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 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.toArray(strlist);
  redis.mset(strlist);   //batch
  System.out.println("success");
  }
  2. 多命令
  msetstring的批量
  hmset hash的批量
  saddset的批量
  如果做到三种命令的混合呢???
  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>  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");
  }
  }
  13、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 usernamejack
  =>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文件中。。。【缩小了文件的尺寸】
  14、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
  (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有密码,可以在这里配置。。。
  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 =
  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");
  }
  15、redis sentinel【哨兵】
  一:sentinel【哨兵】
  master -> slave
  如果master挂掉了,,,程序只能读取,不能写入了。。。
  info:命令获取master集群的所有信息,比如说 slave的ip地址等信息。。。。
  主观: 个人的想法 【不一定真的下线】
  客观: 基本事实   【如果有某几个人都说master挂掉了,才是事实】
  二:搭建
  1. centos-1192.168.23.158    master
  2. centos-2192.168.23.152    slave1
  3. centos-3192.168.23.145    slave2
  4. centos-4192.168.23.154放三台 sentinel。。。。
  《1》 sentinel:
  port
  monitor masterhost masterip
  客观下线: quorum[阈值]
  主观下线: 下线的标准 【】 15s,30s。1min。。。
  其余的采用默认配置。。。
  sentinel auth-pass   =》 master 有密码,在这地方设置。。。
  sentinel monitor   
  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-sentinelsentinel.conf
  ./redis-sentinelsentinel.conf
  ./redis-sentinelsentinel.conf
  ps -ef | grepredis
  当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
  16、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
  redisclient-win32.x86.2.0.exe
  有了可视化工具,就不用每次都输入命令去查看。。。
  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
  # python
  Python 2.7.5 (default, Nov 20 2015, 02:00:19)
   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
  1083mkdir /usr/local/python27
  1084cd Python-2.7.5
  1085ll
  1086./configure --prefix=/usr/local/python27
  1087make
  1088make install
  1089python
  1090mv /usr/bin/python /usr/bin/python2.6.6
  1091ln -s /usr/local/python27/bin/python /usr/bin/python
  1132tar zxvf setuptools-0.6c11.tar.gz
  1133cd setuptools-0.6c11
  1134python setup.py build
  1135python setup.py install
  1136cd ../pip-8.1.2
  1137python setup.pybuild
  1138python setup.pyinstall
  # 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 脚本。。。
  我的配置文件如下:
  # 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
  }
  }
  17、redis cluster
  一: 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
  # ./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):
  # ./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 located at 192.168.23.145:6379
  OK
  192.168.23.145:6379> set password 12345
  -> Redirected to slot 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)机器准备
  机器            端口
  192.168.175.30 7000(主)
  192.168.175.30 7001(主)
  192.168.175.30 7002(主)
  192.168.175.30 7003(从)
  192.168.175.30 7004(从)
  192.168.175.30 7005(从)
  (2)6台配置如下:
  cluster-enabled yes                  开启集群状态
  cluster-config-file nodes-6379.conf    集群的节点文件
  并且改相应的端口。
  安装依赖
  yum install ruby
  (3)启动服务
  ./redis-server ./redis.conf &
  ./redis-trib.rb create --replicas 1 192.168.175.35:7000 192.168.175.35:7001 192.168.175.35:7002 192.168.175.35:7003 192.168.175.35:7004 192.168.175.35:7005
  http://www.iyunv.com/thread-18781-1-1.html
  https://rubygems.org/pages/download
  yum install -y rubygems
  gem install redis
  具体看官网
  https://redis.io/topics/cluster-tutorial
  http://blog.csdn.net/u013820054/article/details/51354189
  ./configure -prefix=/usr/local/ruby
  ##########################################################################################################################
  # ./redis-trib.rb create --replicas 1 192.168.175.35:7000 192.168.175.35:7001 192.168.175.35:7002 192.168.175.35:7003 192.168.175.35:7004 192.168.175.35:7005>>> Creating cluster
  >>> Performing hash slots allocation on 6 nodes...
  Using 3 masters:
  192.168.175.35:7000
  192.168.175.35:7001
  192.168.175.35:7002
  Adding replica 192.168.175.35:7003 to 192.168.175.35:7000
  Adding replica 192.168.175.35:7004 to 192.168.175.35:7001
  Adding replica 192.168.175.35:7005 to 192.168.175.35:7002
  M: 01c5a90a07bb271d47e8845f3952f0b16743cecd 192.168.175.35:7000
  slots:0-5460 (5461 slots) master
  M: 09f977342c6b09ed038522923b823676972418f2 192.168.175.35:7001
  slots:5461-10922 (5462 slots) master
  M: acb67e8e1473caccde89e3262900997e83d27d8a 192.168.175.35:7002
  slots:10923-16383 (5461 slots) master
  S: 7b544a3dbf307e0bc3be7bfd6b2a77369dd1a186 192.168.175.35:7003
  replicates 01c5a90a07bb271d47e8845f3952f0b16743cecd
  S: 0c591fed13413dbb7987025f75ff43c0db32ff17 192.168.175.35:7004
  replicates 09f977342c6b09ed038522923b823676972418f2
  S: bb2d0f0434ffa5e9b8cb8faed0d86d2d4b25a5ab 192.168.175.35:7005
  replicates acb67e8e1473caccde89e3262900997e83d27d8a
  Can I set the above configuration? (type 'yes' to accept): yes
  >>> Nodes configuration updated
  >>> Assign a different config epoch to each node
  >>> Sending CLUSTER MEET messages to join the cluster
  Waiting for the cluster to join....
  >>> Performing Cluster Check (using node 192.168.175.35:7000)
  M: 01c5a90a07bb271d47e8845f3952f0b16743cecd 192.168.175.35:7000
  slots:0-5460 (5461 slots) master
  1 additional replica(s)
  M: acb67e8e1473caccde89e3262900997e83d27d8a 192.168.175.35:7002
  slots:10923-16383 (5461 slots) master
  1 additional replica(s)
  M: 09f977342c6b09ed038522923b823676972418f2 192.168.175.35:7001
  slots:5461-10922 (5462 slots) master
  1 additional replica(s)
  S: 0c591fed13413dbb7987025f75ff43c0db32ff17 192.168.175.35:7004
  slots: (0 slots) slave
  replicates 09f977342c6b09ed038522923b823676972418f2
  S: bb2d0f0434ffa5e9b8cb8faed0d86d2d4b25a5ab 192.168.175.35:7005
  slots: (0 slots) slave
  replicates acb67e8e1473caccde89e3262900997e83d27d8a
  S: 7b544a3dbf307e0bc3be7bfd6b2a77369dd1a186 192.168.175.35:7003
  slots: (0 slots) slave
  replicates 01c5a90a07bb271d47e8845f3952f0b16743cecd
   All nodes agree about slots configuration.
  >>> Check for open slots...
  >>> Check slots coverage...
   All 16384 slots covered.
  redis 192.168.175.35:7000> cluster info
  "cluster_state:ok\r\ncluster_slots_assigned:16384\r\ncluster_slots_ok:16384\r\ncluster_slots_pfail:0\r\ncluster_slots_fail:0\r\ncluster_known_nodes:6\r\ncluster_size:3\r\ncluster_current_epoch:6\r\ncluster_my_epoch:1\r\ncluster_stats_messages_sent:256\r\ncluster_stats_messages_received:256\r\n"
  redis 192.168.175.35:7000> cluster nodes
  "acb67e8e1473caccde89e3262900997e83d27d8a 192.168.175.35:7002 master - 0 1489409919371 3 connected 10923-16383\n09f977342c6b09ed038522923b823676972418f2 192.168.175.35:7001 master - 0 1489409918315 2 connected 5461-10922\n0c591fed13413dbb7987025f75ff43c0db32ff17 192.168.175.35:7004 slave 09f977342c6b09ed038522923b823676972418f2 0 1489409915217 5 connected\nbb2d0f0434ffa5e9b8cb8faed0d86d2d4b25a5ab 192.168.175.35:7005 slave acb67e8e1473caccde89e3262900997e83d27d8a 0 1489409917264 6 connected\n7b544a3dbf307e0bc3be7bfd6b2a77369dd1a186 192.168.175.35:7003 slave 01c5a90a07bb271d47e8845f3952f0b16743cecd 0 1489409921497 4 connected\n01c5a90a07bb271d47e8845f3952f0b16743cecd 192.168.175.35:7000 myself,master - 0 0 1 connected 0-5460\n"
  # redis-cli -p 7000 cluster nodes | grep master
  acb67e8e1473caccde89e3262900997e83d27d8a 192.168.175.35:7002 master - 0 1489414087200 3 connected 10923-16383
  09f977342c6b09ed038522923b823676972418f2 192.168.175.35:7001 master - 0 1489414088131 2 connected 5461-10922
  01c5a90a07bb271d47e8845f3952f0b16743cecd 192.168.175.35:7000 myself,master - 0 0 1 connected 0-5460
  ################
  # pwd
  /root/soft/7000/redis/sbin
  # ./redis-cli-c -p 7000
  127.0.0.1:7000>
  # ./redis-cli--help
  redis-cli 3.2.6
  Usage: redis-cli ]]
  -h       Server hostname (default: 127.0.0.1).
  -p         Server port (default: 6379).
  -s         Server socket (overrides hostname and port).
  -a       Password to use when connecting to the server.
  -r         Execute specified command N times.
  -i       When -r is used, waitsseconds per command.
  It is possible to specify sub-second times like -i 0.1.
  -n             Database number.
  -x               Read last argument from STDIN.
  -d      Multi-bulk delimiter in for raw formatting (default: \n).
  -c               Enable cluster mode (follow -ASK and -MOVED redirections).
  --raw            Use raw formatting for replies (default when STDOUT is
  not a tty).
  --no-raw         Force formatted output even when STDOUT is not a tty.
  --csv            Output in CSV format.
  --stat             Print rolling stats about server: mem, clients, ...
  --latency          Enter a special mode continuously sampling latency.
  --latency-historyLike --latency but tracking latency changes over time.
  Default time interval is 15 sec. Change it using -i.
  --latency-dist   Shows latency as a spectrum, requires xterm 256 colors.
  Default time interval is 1 sec. Change it using -i.
  --lru-test   Simulate a cache workload with an 80-20 distribution.
  --slave            Simulate a slave showing commands received from the master.
  --rdb    Transfer an RDB dump from remote server to local file.
  --pipe             Transfer raw Redis protocol from stdin to server.
  --pipe-timeoutIn --pipe mode, abort with error if after sending all data.
  no reply is received withinseconds.
  Default timeout: 30. Use 0 to wait forever.
  --bigkeys          Sample Redis keys looking for big keys.
  --scan             List all keys using the SCAN command.
  --pattern   Useful with --scan to specify a SCAN pattern.
  --intrinsic-latencyRun a test to measure intrinsic system latency.
  The test will run for the specified amount of seconds.
  --eval       Send an EVAL command using the Lua script at .
  --ldb            Used with --eval enable the Redis Lua debugger.
  --ldb-sync-mode    Like --ldb but uses the synchronous Lua debugger, in
  this mode the server is blocked and script changes are
  are not rolled back from the server memory.
  --help             Output this help and exit.
  --version          Output version and exit.
  Examples:
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  redis-cli --scan --pattern '*:12345*'
  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)
  When no command is given, redis-cli starts in interactive mode.
  Type "help" in interactive mode for information on available commands
  and settings.

页: [1]
查看完整版本: 一步一步学习redis3.2.8