Redis

Redis 是内存数据库,是nosql数据库。
基于key value存储的数据,key只能是string类型, v 可以使多种类型。

 

关系型数据库的索引机制; btree

 

 

  

https://visualgo.net/zh

麻省理工:算法导论:网易公开课
清华大学:数据结构:学堂在线

<<db2  教材 官方>>  join

《深入理解计算机系统》

《MR设计模式》
《nosql精粹?》

  

 

Redis

开源的(BSD协议),使用ANSI  C 编写,基于内存的且支持持久化,高性能的Key-Value的NoSQL数据库
支持数据结构类型丰富,有如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
丰富的支持主流语言的客户端,C、C++、Python、Erlang、R、C#、Java、PHP、Objective-C、Perl、Ruby、Scala、Go、JavaScript

用途:缓存(StackOverFlow)、数据库(微博)、消息中间件(微博)

官方网站: http://www.redis.io

a=1 a=k a=(1,3,98)a={x=11,w=88}    
客户端完成业务

 

 

 

 

行业经验和项目报价和评议比较重要。

  

版本:
分布式  3.18;  伪分布式3.0一下,2.8.18 

单节点部署
安装gcc和tcl准备编译环境
yum install -y gcc tcl 
/root/software
tar -zxvf redis-2.8.18.tar.gz 
 cd redis-2.8.18
 make && make PREFIX=/opt/sxt/redis install  ## 编译复制到opt下
 cd /opt/sxt/redis/
vi /etc/profile  
export REDIS_HOME=/opt/sxt/redis
export PATH=$JAVA_HOME/bin:$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HBASE_HOME/bin:$REDIS_HOME/bin
source /etc/profile

 cd ~/software/redis-2.8.18
 cd utils/
[root@node1 utils]# ./install_server.sh   ## 安装redis 服务端 实例。
Welcome to the redis service installer
This script will help you easily set up a running redis server

Please select the redis port for this instance: [6379] 
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] 
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log] 
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379] 
Selected default - /var/lib/redis/6379
Please select the redis executable path [/opt/sxt/redis/bin/redis-server] 
Selected config:
Port           : 6379
Config file    : /etc/redis/6379.conf
Log file       : /var/log/redis_6379.log
Data dir       : /var/lib/redis/6379
Executable     : /opt/sxt/redis/bin/redis-server
Cli Executable : /opt/sxt/redis/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!

## 一个redis服务可以再一个节点上有多个实例,(选择不同的通讯端口)
## 一个服务实例最多有16个数据库。  从0开始。

## 查看帮助
[root@node1 utils]# redis-server -h
[root@node1 utils]# redis-cli  -h
[root@node1 ~]# redis-cli 
127.0.0.1:6379> help set

  SET key value [EX seconds] [PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

127.0.0.1:6379> set k1 abc
OK
127.0.0.1:6379> get k1
"abc"
127.0.0.1:6379> set k2 5
OK
127.0.0.1:6379> get k2
"5"
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> SETNX k1 dww  ## nx 不存在时才增加(只能添加)
(integer) 0
127.0.0.1:6379> get k1
"abc"
127.0.0.1:6379> set k1 dww xx
OK
127.0.0.1:6379> get k1
"dww"
127.0.0.1:6379> set k2 sdlwlw xx  ## 存在时才修改(只能修改)
OK
127.0.0.1:6379> get k2
"sdlwlw"
127.0.0.1:6379> set k3 sdfdfs xx
(nil)
127.0.0.1:6379> get k3
(nil)
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> type k1
string
127.0.0.1:6379> get k1
"dww"
127.0.0.1:6379> type k2
string
127.0.0.1:6379> get k2
"sdlwlw"
127.0.0.1:6379> set k3 99
OK
127.0.0.1:6379> type k3
string
127.0.0.1:6379> OBJECT encoding k2
"raw"
127.0.0.1:6379> OBJECT encoding k3   ## 属性,可以看到string是否适合位运算。
"int"
127.0.0.1:6379> get k3
"99"

  

127.0.0.1:6379> help MGET MGET key [key ...] summary: Get the values of all the given keys since: 1.0.0 group: string 127.0.0.1:6379> keys * 1) "k3" 2) "k1" 3) "k2" 127.0.0.1:6379> MSET k4 5 k5 abc k6 werw OK 127.0.0.1:6379> keys * 1) "k5" 2) "k6" 3) "k1" 4) "k4" 5) "k3" 6) "k2" 127.0.0.1:6379> MSETNX k6 dfsd k7 dkfd (integer) 0 127.0.0.1:6379> keys * 1) "k5" 2) "k6" 3) "k1" 4) "k4" 5) "k3" 6) "k2" 127.0.0.1:6379> MSETNX k7 dfsd k8 dkfd (integer) 1 127.0.0.1:6379> keys * 1) "k7" 2) "k5" 3) "k6" 4) "k1" 5) "k4" 6) "k8" 7) "k3" 8) "k2" 127.0.0.1:6379> MSETNX k9 eerw k8 ewrwe (integer) 0 127.0.0.1:6379> keys * 1) "k7" 2) "k5" 3) "k6" 4) "k1" 5) "k4" 6) "k8" 7) "k3" 8) "k2" 127.0.0.1:6379> set kab www OK 127.0.0.1:6379> keys * 1) "kab" 2) "k5" 3) "k4" 4) "k1" 5) "k3" 6) "k8" 7) "k2" 8) "k7" 9) "k6" 127.0.0.1:6379> keys ? ## 正则匹配一个字符 (empty list or set) 127.0.0.1:6379> keys ?? 1) "k5" 2) "k4" 3) "k1" 4) "k3" 5) "k8" 6) "k2" 7) "k7" 8) "k6" 127.0.0.1:6379> keys ??? ## 匹配三个字符 1) "kab" 127.0.0.1:6379> type k1 string 127.0.0.1:6379> STRLEN ke (integer) 0 127.0.0.1:6379> STRLEN k1 (integer) 3 127.0.0.1:6379> STRLEN k3 (integer) 2 127.0.0.1:6379> FLUSHALL ## 清空所有数据 OK 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> set k21 werwe OK 127.0.0.1:6379> FLUSHDB ## 清空数据库 OK 127.0.0.1:6379> keys * (empty list or set) [root@node1 ~]# redis-cli -n 1 127.0.0.1:6379[1]> get k1 (nil) 127.0.0.1:6379[1]> keys * (empty list or set) 127.0.0.1:6379[1]> quit [root@node1 ~]# redis-cli 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> get k1 (nil) 127.0.0.1:6379> set k1 a OK 127.0.0.1:6379> get ki (nil) 127.0.0.1:6379> get k1 "a" 127.0.0.1:6379> exit [root@node1 ~]# redis-cli -n 1 ##链接数据库1 127.0.0.1:6379[1]> get k1 (nil) 127.0.0.1:6379[1]> keys * (empty list or set) 127.0.0.1:6379[1]> quit [root@node1 ~]# redis-cli -n 0 127.0.0.1:6379> get k1 "a" 127.0.0.1:6379> set k2 99 OK 127.0.0.1:6379> STRLEN k2 (integer) 2 127.0.0.1:6379> set k3 999 OK 127.0.0.1:6379> STRLEN k3 (integer) 3 127.0.0.1:6379> set k4 中 ## xshell是utf-8 OK 127.0.0.1:6379> STRLEN k4 (integer) 3 127.0.0.1:6379> set k5 中 OK 127.0.0.1:6379> STRLEN k5 (integer) 3
[root@node1 ~]# redis-cli           ## xhsell选择gbk编码链接时。
127.0.0.1:6379> set k5 中
OK
127.0.0.1:6379> STRLEN k5
(integer) 2

  


127.0.0.1:6379> [root@node1 ~]# redis-cli -n 0 127.0.0.1:6379> get k4 ##展示的是字节码 "\xe4\xb8\xad" 127.0.0.1:6379> [root@node1 ~]# redis-cli --raw ##原始数据类型显示 127.0.0.1:6379> get k4 中 127.0.0.1:6379> get k5 א 127.0.0.1:6379> get k4 中 127.0.0.1:6379> [root@node1 ~]# redis-cli 127.0.0.1:6379> EXISTS k5 (integer) 1 127.0.0.1:6379> get k1 "a" 127.0.0.1:6379> GETSET k1 b "a" 127.0.0.1:6379> get k1 "b" 127.0.0.1:6379> APPEND k1 bd (integer) 3 127.0.0.1:6379> get k1 "bbd" 127.0.0.1:6379> get k1 "bbd" 127.0.0.1:6379> append k1 werw (integer) 7 127.0.0.1:6379> get k1 "bbdwerw" 127.0.0.1:6379> GETRANGE (error) ERR wrong number of arguments for 'getrange' command 127.0.0.1:6379> help GETRANGE GETRANGE key start end summary: Get a substring of the string stored at a key since: 2.4.0 group: string 127.0.0.1:6379> GETRANGE k1 3 (error) ERR wrong number of arguments for 'getrange' command 127.0.0.1:6379> GETRANGE k1 3 -1 "werw" 127.0.0.1:6379> GETRANGE k1 -2 -2 "r" 127.0.0.1:6379> get k1 "bbdwerw" 127.0.0.1:6379> INCR k1 (error) ERR value is not an integer or out of range 127.0.0.1:6379> FLUSHALL OK 127.0.0.1:6379> set k1 99 OK 127.0.0.1:6379> INCR k1 ## 数值类型自增长 (integer) 100 127.0.0.1:6379> INCR k1 (integer) 101 127.0.0.1:6379> INCR k1 (integer) 102 127.0.0.1:6379> DECR k1 (integer) 101 127.0.0.1:6379> DECR k1 (integer) 100 127.0.0.1:6379> INCRBY k1 5 (integer) 105 127.0.0.1:6379> INCRBY k1 5 ## 数值类型自增长步长 (integer) 110 127.0.0.1:6379> INCRBYFLOAT 5.5 (error) ERR wrong number of arguments for 'incrbyfloat' command 127.0.0.1:6379> INCRBYFLOAT k1 5.5 "115.5" 127.0.0.1:6379> SETBIT k1 1 1 (integer) 0 127.0.0.1:6379> get k1 "q15.5" 127.0.0.1:6379> get k1 "q15.5" 127.0.0.1:6379> FLUSHALL OK 127.0.0.1:6379> SETBIT k1 1 1 ## 位图数据 1byte 01000000 sacii 表的64 = @ (integer) 0 127.0.0.1:6379> get k1 "@" 127.0.0.1:6379> help SETBIT SETBIT key offset value summary: Sets or clears the bit at offset in the string value stored at key since: 2.2.0 group: string 127.0.0.1:6379> SETBIT k1 7 1 1byte 01000001 (integer) 0 127.0.0.1:6379> get k1 "A" 127.0.0.1:6379> SETBIT k1 9 1 2byte 01000001 01000000 A@ (integer) 0 127.0.0.1:6379> get k1 "A@" 127.0.0.1:6379>

  

  

 

 

 

 

 

 

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SETBIT k1 1 1
(integer) 0
127.0.0.1:6379> get k1
"@"
127.0.0.1:6379> SETBIT k1 7 1
(integer) 0
127.0.0.1:6379> get k1
"A"
127.0.0.1:6379> SETBIT k1 9 1
(integer) 0
127.0.0.1:6379> get k1
"A@"
127.0.0.1:6379> GETBIT k1 9
(integer) 1
127.0.0.1:6379> GETBIT k1 1
(integer) 1
127.0.0.1:6379> GETBIT k1 7
(integer) 1
127.0.0.1:6379> GETBIT k1 6
(integer) 0
127.0.0.1:6379> BITPOS k1 1 
(integer) 1
127.0.0.1:6379> BITPOS k1 1 0 0
(integer) 1
127.0.0.1:6379> BITPOS k1 1 0 1
(integer) 1
127.0.0.1:6379> SETBIT k1 1 0
(integer) 1
127.0.0.1:6379> BITPOS k1 1 0 1
(integer) 7
127.0.0.1:6379> SETBIT k1 7 0
(integer) 1
127.0.0.1:6379> BITPOS k1 1 0 1
(integer) 9
### 解释
0000000  01000000
127.0.0.1:6379> BITPOS k1 1 0 1
查找1在0~1的字节索引中的二进制位索引(偏移量)

  

 

 

 

 

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SETBIT k1 1 1
(integer) 0
127.0.0.1:6379> SETBIT k2 7 1
(integer) 0
127.0.0.1:6379> BITOP and k3 k1 k2
(integer) 1
127.0.0.1:6379> get k3
"\x00"
127.0.0.1:6379> BITOP or k4 k1 k2
(integer) 1
127.0.0.1:6379> get k4
"A"

  

127.0.0.1:6379> help BITCOUNT

  BITCOUNT key [start] [end]
  summary: Count set bits in a string
  since: 2.6.0
  group: string

127.0.0.1:6379> SETBIT k1 7 1
(integer) 0
127.0.0.1:6379> SETBIT k1 9 1
(integer) 0
127.0.0.1:6379> BITCOUNT k1 0 0
(integer) 2
127.0.0.1:6379> BITCOUNT k1 0 1
(integer) 3
## 统计字节区间范围内的二进制总数
127.0.0.1:6379> BITCOUNT k1 0 -1
(integer) 3
127.0.0.1:6379> BITCOUNT k1 -2 -1

  

 

 

一年内某用户上线次数: 365为bit, 每天对应一个位,0,1表示上线。

 

 

 

 

 

 

 

 

 

 

 

127.0.0.1:6379> LPUSH l1 a
(integer) 1
127.0.0.1:6379> LPUSH l1 b c d e f
(integer) 6
127.0.0.1:6379> LRANGE l1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> LRANGE l1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> LPOP l1
"f"
127.0.0.1:6379> LPOP l1
"e"
127.0.0.1:6379> LPOP l1
"d"
127.0.0.1:6379> LPOP l1
"c"
127.0.0.1:6379> LPOP l1
"b"
127.0.0.1:6379> LPOP l1
"a"
127.0.0.1:6379> LPOP l1
(nil)
127.0.0.1:6379> LRANGE l1 0 -1
(empty list or set)
127.0.0.1:6379> LPUSH l1 b c d e f
(integer) 5
127.0.0.1:6379> RPOP l1
"b"
127.0.0.1:6379> RPOP l1
"c"
127.0.0.1:6379> RPOP l1
"d"
127.0.0.1:6379> RPOP l1
"e"
127.0.0.1:6379> RPOP l1
"f"
## 从左到右,从上到下  [f e d c b] 
127.0.0.1:6379> LPUSH l1 b c d e f
(integer) 5
127.0.0.1:6379> LRANGE l1 1 1
1) "e"
127.0.0.1:6379> LRANGE l1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
127.0.0.1:6379> LRANGE l1 -2 -1
1) "c"
2) "b"
127.0.0.1:6379> LRANGE l1 -1 -2
(empty list or set)
127.0.0.1:6379> LPUSH l1 b c d e f
(integer) 5
127.0.0.1:6379> RPOPLPUSH l1 l2
"b"
127.0.0.1:6379> LRANGE l2 0 -1
1) "b"
127.0.0.1:6379> LRANGE l1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"

  

  

 

 

 

 

127.0.0.1:6379> LINDEX l1 2
"d"
127.0.0.1:6379> LLEN l1
(integer) 4
127.0.0.1:6379> RPUSH listkey c abc c ab 123 ab bj ab redis list
(integer) 10
127.0.0.1:6379> LRANGE listkey 0 -1
 1) "c"
 2) "abc"
 3) "c"
 4) "ab"
 5) "123"
 6) "ab"
 7) "bj"
 8) "ab"
 9) "redis"
10) "list"
127.0.0.1:6379> LREM listkey -1 ab
(integer) 1
127.0.0.1:6379> LRANGE listkey 0 -1
1) "c"
2) "abc"
3) "c"
4) "ab"
5) "123"
6) "ab"
7) "bj"
8) "redis"
9) "list"
127.0.0.1:6379> LREM listkey 0 ab
(integer) 2
127.0.0.1:6379> LRANGE listkey 0 -1
1) "c"
2) "abc"
3) "c"
4) "123"
5) "bj"
6) "redis"
7) "list"
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> RPUSH listkey c abc c ab 123 ab bj ab redis list
(integer) 10
127.0.0.1:6379> help LTRIM

  LTRIM key start stop
  summary: Trim a list to the specified range
  since: 1.0.0
  group: list

127.0.0.1:6379> LTRIM listkey 0 -1
OK
127.0.0.1:6379> LRANGE listkey 0 -1
 1) "c"
 2) "abc"
 3) "c"
 4) "ab"
 5) "123"
 6) "ab"
 7) "bj"
 8) "ab"
 9) "redis"
10) "list"
127.0.0.1:6379> LTRIM listkey 0 0
OK
127.0.0.1:6379> LRANGE listkey 0 -1   ## 去除指定范围外的元素
1) "c"
127.0.0.1:6379> LPUSH l3 a b d
(integer) 3
127.0.0.1:6379> LRANGE l3 0 -1
1) "d"
2) "b"
3) "a"
127.0.0.1:6379> LINSERT l3 before b x
(integer) 4
127.0.0.1:6379> LRANGE l3 0 -1
1) "d"
2) "x"
3) "b"
4) "a"

  

 

 

 

 

windowA
127.0.0.1:6379> BLPOP l1 0
windowB
127.0.0.1:6379> BLPOP l1 0
windowC
127.0.0.1:6379> BLPOP l1 0
windowD
127.0.0.1:6379> LPUSH l1 1
windowA
127.0.0.1:6379> BLPOP l1 0  ## 阻塞中断
1) "l1"
2) "1"
(92.45s)
windowD
127.0.0.1:6379> LPUSH l1 1
windowB
127.0.0.1:6379> BLPOP l1 0  ## 阻塞中断
1) "l1"
2) "1"
127.0.0.1:6379> BLPOP l1 5  ## 5秒自动中断
(nil)
(5.93s)

  

 

 

 

 

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> HSET mike name michael
(integer) 1
127.0.0.1:6379> HSET mike age 30
(integer) 1
127.0.0.1:6379> HMSET mike gender m phone 13552594619
OK
127.0.0.1:6379> HVALS mike
1) "michael"
2) "30"
3) "m"
4) "13552594619"
127.0.0.1:6379> HKEYS mike
1) "name"
2) "age"
3) "gender"
4) "phone"
127.0.0.1:6379> set mike:name michael
OK
127.0.0.1:6379> set mike:age 30
OK
127.0.0.1:6379> set mike:gender m
OK
127.0.0.1:6379> keys *
1) "mike:age"
2) "mike:name"
3) "mike"
4) "mike:gender"
127.0.0.1:6379> HGET mike age
"30"
127.0.0.1:6379> HGET mike name
"michael"
127.0.0.1:6379> HLEN mike
(integer) 4
127.0.0.1:6379> HGETALL mike
1) "name"
2) "michael"
3) "age"
4) "30"
5) "gender"
6) "m"
7) "phone"
8) "13552594619"
127.0.0.1:6379> HINCRBY mike age 10
(integer) 40
127.0.0.1:6379> HINCRBY mike age 10.5
(error) ERR value is not an integer or out of range
127.0.0.1:6379> HINCRBYFLOAT mike age 10.5
"50.5"

  

 

 

redis key分时点存储,到时点时去检查时间片下的数据是否过期。被动
当用户查询数据时,检查是否过期。 被动

 

 

 

 

 

 

  

127.0.0.1:6379> SADD s1 mike marie peter marry
(integer) 4
127.0.0.1:6379> SMEMBERS s1
1) "peter"
2) "marie"
3) "mike"
4) "marry"
127.0.0.1:6379> SREM s1 peter
(integer) 1
127.0.0.1:6379> SMEMBERS s1
1) "marie"
2) "mike"
3) "marry"
127.0.0.1:6379> SISMEMBER s1 peter
(integer) 0
127.0.0.1:6379> SISMEMBER s1 marry
(integer) 1

 

127.0.0.1:6379> SRANDMEMBER s1 
"marry"
127.0.0.1:6379> SRANDMEMBER s1 
"marie"
127.0.0.1:6379> SRANDMEMBER s1 1
1) "marry"
127.0.0.1:6379> SRANDMEMBER s1 2
1) "mike"
2) "marry"
127.0.0.1:6379> SRANDMEMBER s1 10
1) "mike"
2) "marie"
3) "marry"
127.0.0.1:6379> SRANDMEMBER s1 -100  ## 超过集合数量时,返回数量个。
  1) "mike"
  2) "marry"
  3) "marry"
  4) "marie"
  5) "mike"
  6) "marry"
  7) "marry"
...100

127.0.0.1:6379> SRANDMEMBER s1 -2
1) "mike"
2) "marry"
127.0.0.1:6379> SPOP s1
"mike"
127.0.0.1:6379> SPOP s1
"marie"
127.0.0.1:6379> SCARD s1
(integer) 1

  

 

  

 

 

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD number1 123 456 789
(integer) 3
127.0.0.1:6379> SADD number2 123 456 999
(integer) 3
127.0.0.1:6379> SDIFFSTORE number3 number1 number2  ## number1 去除1与2的交集
(integer) 1
127.0.0.1:6379> SMEMBERS number3
1) "789"
127.0.0.1:6379> SDIFFSTORE number4 number2 number1
(integer) 1
127.0.0.1:6379> SMEMBERS number4
1) "999"
127.0.0.1:6379> SUNION number5 number1 number2
1) "123"
2) "456"
3) "789"
4) "999"
127.0.0.1:6379> SINTER number1 number2
1) "123"
2) "456"

  

 

 

 

 

 

 

 

 

127.0.0.1:6379> ZADD fruits 3.2 香蕉
(integer) 1
127.0.0.1:6379> ZADD fruits 2.0 西瓜
(integer) 1
127.0.0.1:6379> ZADD fruits 4.0 番石榴 7.0 梨 6.8 芒果
(integer) 3
127.0.0.1:6379> ZRANGE fruits
(error) ERR wrong number of arguments for 'zrange' command
127.0.0.1:6379> ZRANGE fruits
(error) ERR wrong number of arguments for 'zrange' command
127.0.0.1:6379> ZRANGE fruits 0 -1
1) "\xe8\xa5\xbf\xe7\x93\x9c"
2) "\xe9\xa6\x99\xe8\x95\x89"
3) "\xe7\x95\xaa\xe7\x9f\xb3\xe6\xa6\xb4"
4) "\xe8\x8a\x92\xe6\x9e\x9c"
5) "\xe6\xa2\xa8"
127.0.0.1:6379> quit
[root@node1 ~]# redis-cli --raw
127.0.0.1:6379> ZRANGE fruits 0 -1
西瓜
香蕉
番石榴
芒果
梨
127.0.0.1:6379> ZRANGE fruits 0 -1 withscores
西瓜
2
香蕉
3.2000000000000002
番石榴
4
芒果
6.7999999999999998
梨
7
127.0.0.1:6379> ZREVRANGE fruits 0 -1 withscores
梨
7
芒果
6.7999999999999998
番石榴
4
香蕉
3.2000000000000002
西瓜
2
127.0.0.1:6379> ZRANGE fruits -3 -1
番石榴
芒果
梨
127.0.0.1:6379> ZRANGE fruits -3 -1 withscores
番石榴
4
芒果
6.7999999999999998
梨
7

  

127.0.0.1:6379> ZSCORE fruits 芒果
6.7999999999999998
127.0.0.1:6379> ZINCRBY fruits 1.5 芒果
8.3000000000000007
127.0.0.1:6379> ZRANGE fruits 0 -1 
西瓜
香蕉
番石榴
梨
芒果
127.0.0.1:6379> ZRANK fruits 西瓜
0
127.0.0.1:6379> ZRANK fruits 西瓜
0
127.0.0.1:6379> ZREVRANK fruits 番石榴
2
127.0.0.1:6379> ZREVRANK fruits 芒果
0
127.0.0.1:6379> ZRANGE fruits 3 4 withscores
梨
7
芒果
8.3000000000000007
127.0.0.1:6379> ZRANGEBYSCORE fruits 3 3.5 withscores
香蕉
3.2000000000000002
127.0.0.1:6379> ZRANGEBYSCORE fruits (3.2 3.5 withscores

127.0.0.1:6379> ZRANGEBYSCORE fruits -inf +inf withscores
西瓜
2
香蕉
3.2000000000000002
番石榴
4
梨
7
芒果
8.3000000000000007
127.0.0.1:6379> ZREMRANGEBYRANK fruits 0 0
1
127.0.0.1:6379> ZRANGEBYSCORE fruits -inf +inf withscores
香蕉
3.2000000000000002
番石榴
4
梨
7
芒果
8.3000000000000007
127.0.0.1:6379> ZCARD fruits ## 返回元素个数
4
127.0.0.1:6379> ZCOUNT fruits 4 7   ## 分值范围内元素的个数
2
127.0.0.1:6379> ZCOUNT fruits 5 7
1

  

 

 

  

举例
ZADD scores1 70 tom 80 peter 60 john
ZADD scores2 90 peter 60 ben
ZUNIONSTORE scores-all 2 scores1 scores2
ZUNIONSTORE scores-all1 2 scores1 scores2 AGGREGATE SUM
ZUNIONSTORE scores-all2 2 scores1 scores2 WEIGHTS 1 0.5 

 

127.0.0.1:6379> ZADD scores1 70 tom 80 peter 60 john
3
127.0.0.1:6379> ZADD scores2 90 peter 60 ben
2
127.0.0.1:6379> ZUNIONSTORE scores3 2 scores1 scores2
4
127.0.0.1:6379> ZRANGE scores3 0 -1 withscores
ben
60
john
60
tom
70
peter
170
127.0.0.1:6379> ZUNIONSTORE scores-all1 2 scores1 scores2 AGGREGATE SUM
4
127.0.0.1:6379> ZRANGE scores-all1 0 -1 withscores
ben
60
john
60
tom
70
peter
170
127.0.0.1:6379> ZUNIONSTORE scores-all2 2 scores1 scores2 WEIGHTS 1 0.5 AGGREGATE SUM
4
127.0.0.1:6379> ZRANGE scores-all2 0 -1 withscores
ben
30
john
60
tom
70
peter
125

  

 

 

 

 

 

 

 

 

 

 

 

  

 

mysql索引 btree https://www.jianshu.com/p/0371c9569736
跳跃表
https://blog.csdn.net/qpzkobe/article/details/80056807

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

AOF开启之后,RDB就不会被采纳。

 

 

 

 

 

 

数据承载的方式:
集群  分片   3台4G内存,最多承载12G数据,每一台4G,只是缺少备份
lvs    镜像全量   3台4G内存,  一模一样的机器和数据,最多承载4G

  

 

 

  

 

 

CAP原则
https://baike.baidu.com/item/CAP%E5%8E%9F%E5%88%99/5712863?fr=aladdin
无主模型

主从模型

 

sentinel
英 ['sentɪn(ə)l]  美 ['sɛntɪnl] 
n. 哨兵
vt. 守卫,放哨

 

https://www.jianshu.com/p/d9d067a8a086 paxos 论文: 分布式系统一致性的基本理论

  

 

 

 

 

官网,和java client源码
https://redis.io/clients

https://github.com/xetorthio/jedis

  

 

 

伪分布式搭建
node1上
[root@node1 ~]# mkdir redis
[root@node1 redis]# mkdir 6380
[root@node1 redis]# mkdir 6381
[root@node1 redis]# mkdir 6382
[root@node1 redis]# cd 6380/
[root@node1 6380]# redis-server -h
[root@node1 6380]# redis-server -port 6380   ## 默认异master身份启动
[root@node1 6381]# pwd
/root/redis/6381
[root@node1 6381]# redis-server --port 6381 --slaveof 127.0.0.1 6380  ## 启动slave
[root@node1 6382]# redis-server --port 6382 --slaveof 127.0.0.1 6380

[root@node1 ~]# redis-cli -p 6380
127.0.0.1:6380> set k1 5
OK
127.0.0.1:6380> get k1
"5"
[root@node1 ~]# redis-cli -p 6381
127.0.0.1:6381> get k1
"5"
[root@node1 ~]# redis-cli -p 6382
127.0.0.1:6382> get k1
"5"
127.0.0.1:6382> set k3 dsfsd       ## slave 只能读,不能写,master才能够写入
(error) READONLY You can't write against a read only slave. 

## 当6380 ctrl+c挂掉之后。

  

127.0.0.1:6381> SLAVEOF no one ## 6381手动成为master 
127.0.0.1:6381> set k3 dfsd
OK
[root@node1 6380]# redis-server --port 6380 --slaveof 127.0.0.1 6381  ## 启动6380称为81的slave

not connected> get k3
"dfsd"
127.0.0.1:6380> set k4 werwe
(error) READONLY You can't write against a read only slave.

## 如上手动切换比较麻烦。

  

 

哨兵,单独存在的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

配置和启动
[root@node1 src]# cp redis-sentinel /opt/sxt/redis/bin
[root@node1 src]# ls /opt/sxt/redis/bin/
redis-benchmark  redis-check-aof  redis-check-dump  redis-cli  redis-sentinel  redis-server
[root@node1 src]# cd
[root@node1 ~]# mkdir sent
[root@node1 ~]# cd sent/
[root@node1 sent]# vi s1.conf
[root@node1 sent]# cp s1.conf s2.conf
[root@node1 sent]# cp s1.conf s3.conf
[root@node1 sent]# vi s2.conf 
[root@node1 sent]# vi s3.conf 
[root@node1 sent]# cat s*.conf
port 23680
sentinel monitor sxt 127.0.0.1 6380 2
port 23681
sentinel monitor sxt 127.0.0.1 6380 2
port 23682
sentinel monitor sxt 127.0.0.1 6380 2


[root@node1 6380]# redis-server --port 6380
[root@node1 6381]# redis-server --port 6381 --slaveof 127.0.0.1 6380
[root@node1 6382]# redis-server --port 6382 --slaveof 127.0.0.1 6380

[root@node1 sent]# redis-sentinel s1.conf   ## ~/sent ## 启动哨兵
[root@node1 sent]# redis-sentinel s2.conf 
[root@node1 sent]# redis-sentinel s3.conf  
## ctrl+c结束6380服务。
## 稍等一会,哨兵自动选举,
s2,s3下的日志
[10204] 14 Sep 14:33:28.946 # +switch-master sxt 127.0.0.1 6380 127.0.0.1 6382
## 此时6382称为主

## 重新启动6380,以master身份。
[root@node1 6380]# redis-server --port 6380  ## 此时6382还是master,6380是slave.

  

Redis3.0提供了集群解决方案

  

 

 

 

 

 

slot
英 [slɒt]  美 [slɑt] 
n. 位置;狭槽;水沟;硬币投币口
vt. 跟踪;开槽于

  

 

 

 

 

3.0的节点既是节点又是哨兵的功能。

redis集群环境搭建
[root@node1 redis-cluster]# pwd
/root/software/redis-cluster
[root@node1 redis-cluster]# ll
total 1432
-rw-r--r--. 1 root root 1364993 Jun  4  2018 redis-3.0.4.tar.gz
-rw-r--r--. 1 root root   92160 Jun  4  2018 redis-3.3.0.gem   ## 依赖ruby环境
drwxr-xr-x. 8 root root    4096 Sep 14 15:25 redis-test
[root@node1 redis-cluster]# tar xf redis-3.0.4.tar.gz 

[root@node1 redis-cluster]# cd redis-3.0.4
[root@node1 redis-3.0.4]# whereis gcc tcl
[root@node1 redis-3.0.4]# make && make PREFIX=/opt/sxt/redis/  install
[root@node1 redis-3.0.4]# cd /opt/sxt/redis/
[root@node1 redis]# ls
bin
[root@node1 redis]# cd bin/
[root@node1 bin]# ll
total 8520
-rwxr-xr-x. 1 root root 2077192 Sep 14 15:29 redis-benchmark
-rwxr-xr-x. 1 root root   25104 Sep 14 15:29 redis-check-aof
-rwxr-xr-x. 1 root root   55936 Sep 14 15:29 redis-check-dump
-rwxr-xr-x. 1 root root 2201240 Sep 14 15:29 redis-cli
lrwxrwxrwx. 1 root root      12 Sep 14 15:29 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 4352016 Sep 14 15:29 redis-server
[root@node1 bin]# cd ~/software/redis-cluster/
[root@node1 redis-cluster]# ls
redis-3.0.4  redis-3.0.4.tar.gz  redis-3.3.0.gem  redis-test
[root@node1 redis-cluster]# yum -y install ruby rubygems   ## 安装ruby环境
[root@node1 redis-cluster]# ls
redis-3.0.4  redis-3.0.4.tar.gz  redis-3.3.0.gem  redis-test
[root@node1 redis-cluster]# gem install --local redis-3.3.0.gem  ## 本地安装gem(redis依赖ruby组件)
[root@node1 redis-cluster]# cd redis-test/
[root@node1 redis-test]# ls
7000  7001  7002  7003  7004  7005
[root@node1 redis-test]# cd 7000/
-rw-r--r--. 1 root root 30 Jun  4  2018 redis.conf
[root@node1 7000]# cat redis.conf     ## 每个文件加下的配置对应700x
cluster-enabled yes
port 7000
###通过单节点演示6个实例;node1 打开6个终端 进入各个700x文件夹
[root@node1 7000]# pwd
/root/software/redis-cluster/redis-test/7000
## 6个终端都启动实例 执行 redis-server r*
[root@node1 7000]# redis-server r*    ## 相当于6个无主的实例
##指定集群  前三个是主,后三个是备
[root@node1 src]# ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
> 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
[root@node1 src]# redis-cli -p 7000    ## 错误 应该-c
127.0.0.1:7000> set k1 5
(error) MOVED 12706 127.0.0.1:7002
127.0.0.1:7000>     
[root@node1 src]# redis-cli -p 7000 -c     ## -c以集群方式进入
127.0.0.1:7000> set k1 5 
-> Redirected to slot [12706] located at 127.0.0.1:7002  ## 槽位和数据
OK
127.0.0.1:7002> set k2 10
-> Redirected to slot [449] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get k2
"10"
127.0.0.1:7000> get k1
-> Redirected to slot [12706] located at 127.0.0.1:7002
"5"
[root@node1 ~]# redis-cli -p 7000 -c
127.0.0.1:7000> get k1
-> Redirected to slot [12706] located at 127.0.0.1:7002
"5"
127.0.0.1:7002> exit
[root@node1 ~]# redis-cli -p 7003 -c
127.0.0.1:7003> get k1
-> Redirected to slot [12706] located at 127.0.0.1:7002
"5"
127.0.0.1:7002> exit
## 将7000 ctrl+c结束, 此时,7003备接替。get k1时,不会重定向
[root@node1 ~]# redis-cli -p 7003 -c
127.0.0.1:7003> get k2
"10"

 

redis-shake进展:
  请选择版本号为:redis-6.2   redis-shake-v2.1 实验同步成功;


1.架构
    注意版本问题:我本地用的是5.0.14版本

redis-cluster-A 
7000 7001 7002 是master 7003 7004 7005是slave
redis-cluster-B
7000 7001 7002 是master 7003 7004 7005是slave
redis-shake


2.安装
redis安装步骤:
https://redis.io/docs/getting-started/installation/install-redis-from-source/
https://blog.csdn.net/dingxiaoyao1985/article/details/124019087

https://www.redis.com.cn/topics/cluster-tutorial.html
  
wget https://download.redis.io/redis-stable.tar.gz

tar -xzvf redis-stable.tar.gz cd redis-stable
make
如果报错,请执行如下命令:
sudo apt-get install -y make
sudo apt-get install -y pkg-config
apt-get install -y gcc automake autoconf libtool
make distclean

 make install PREFIX=/home/test/redistest/redis

mkdir cluster
test@ubuntu20:~/redistest/cluster$ pwd
/home/test/redistest/cluster
 cd cluster/
 mkdir 7000 7001 7002 7003 7004 7005

vim 7000/redis.conf
cluster-enable yes
port 7000

cp 7000/redis.conf ./7001/  
sed -i 's/8000/8001/g' 8001/redis.conf
../redis-server redis.conf
../../bin/redis-server ./redis.conf

test@ubuntu20:~/redistest/redis/cluster/7005$ pwd
/home/test/redistest/redis/cluster/7005    (需要到当前目录下执行,生产的nodes.conf,appendonlydir文件才不会被相互覆盖)
test@ubuntu20:~/redistest/redis/cluster/7005$ cat redis.conf
port 7005
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes # redis后台运行

启动服务:
test@ubuntu20:~/redistest/redis/cluster/7005$ ../../bin/redis-server ./redis.conf &


scp -r redis test@192.168.79.151:/home/test/redistest

创建集群
Redis5通过redis-cli就可以创建集群;Redis3或4需要使用redis集群的命令工具redis-trib。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005  --cluster-replicas 1

登录节点  -c 连接集群结点时使用
 ./bin/redis-cli -c -p 7000
 
 查看:集群状态


https://blog.csdn.net/m0_67390969/article/details/124121711

redis-cli -h ip -p 9379 -a password cluster info
redis-cli -p 7000  cluster info
redis-cli -p 7005   info
redis-cli -p 7005  cluster nodes

https://help.aliyun.com/document_detail/125941.html?spm=a2c4g.11186623.6.628.c1c94ddcX5gbCE

 

 

 

 

同步数据:
vim redis-shake.conf
source.type = cluster
source.address = 192.168.79.152:7003;192.168.79.152:7004;192.168.79.152:7005
target.type = cluster
target.address = 192.168.79.151:7000;192.168.79.151:7001;192.168.79.151:7002
rewrite = true

./redis-shake -type=sync -conf=redis-shake.conf

./redis-shake.linux -type=sync -conf=redis-shake.conf

其他帮助命令
杀死所有redis进程
for i in `ps -ef|grep redis |awk '{print $2}' `; do kill -9 $i ; done;

 

 https://help.aliyun.com/document_detail/125941.html?spm=a2c4g.11186623.6.628.c1c94ddcX5gbCE

https://help.aliyun.com/document_detail/111066.html?spm=a2c4g.11186623.6.625.52597ce0BQ1GwU

 

redis版本

redis-shake版本

是否报错

是否同步成功

redis-6.2.7

redis-shake-v2.1.2

 

 成功

redis-7.0.0

redis-shake-v2.1.2

[invalid RDB version number 10, 9]

 失败

redis-5.0.14

redis-shake-v2.1.2,

redis-shake-v2.0.3

失败(查询不到同步数据)

posted @ 2019-09-12 23:29  星回中道  阅读(346)  评论(0编辑  收藏  举报