Redis详解

一、Redis安装

二、Redis命令

三、StackExchange.Redis

四、四大结构体

五、Redis数据结构之String

六、Redis数据结构之List

七、Redis数据结构之Hash表

八、Redis数据结构之Set

九、Redis数据结构之sorted_set

十、Redis数据结构之hyperloglog

十一、Transactions

十二、发布/订阅

十三、redis驱动批量执行命令

十四、Redis使用Lua

十五、Redis两种持久化方式

十六、搭建Redis主-备(mster-slave)

十七、搭建Redis主-备(mster-slave)+哨兵(sentinel)

十八、 web监控【redislive】

十九、 搭建cluster(集群) 

redis中文文档:http://www.redis.cn/

redis可视化工具:https://raw.githubusercontent.com/caoxinyu/RedisClient/windows/release/redisclient-win32.x86.2.0.exe

一、Redis安装

1,Windows安装

①下载redis并安装msi文件

https://github.com/MicrosoftArchive/redis

②设置环境变量

 

③运行server

redis-server D:Redis edis.windows-service.conf

④运行client

redis-cli

2,Linux安装

①进入usr-》local目录下

②$ wget http://download.redis.io/releases/redis-4.0.6.tar.gz   下载redis

③$ tar xzf redis-4.0.6.tar.gz  解压

④$ cd redis-4.0.6  进入目录

⑤$ make  编译

⑥编译好之后进入src文件下,发现编译好了几个可执行文件。将这几个文件考到sbin下面

⑦配置环境变量

/etc/profile 打开文件,设置

export PATH=$PATH:/usr/local/redis-4.0.6/sbin

⑧重启centOS 

二、Redis命令

set username jack 设置缓存

get username 读取缓存

keys * 查看所有的key

flushall 清空所有数据(没有一点安全保证)

bgsave 立马持久化缓存信息

bind 127.0.0.1  如果没有注销掉bind,则Redis监听所有链接

protected-mode yes【yes只能回路地址127.0.0.1 本地访问】

生产环境一般配置
#bind
protected-mode no

port 6379 配置redis端口

dir ./ 配置rdb和logfile的存放位置(例如:dir /usr/redis/sbin/db)

databases 16设置数据库的数量

logfile "server_log.txt" 指定日志文件名称

loglevel notice 日志记录级别

rename-command 改变命令的名称

redis-cli -h 192.168.1.102 -p 6379 远程链接redis

redis-cli -h 192.168.1.102 -p 6379 -a 123456 --stat 监控redis状态

设置密码:

在配置文件中设置requirepass(例如 requirepass 123456)
连接redis服务器时需要带上密码(例如:redis-cli -h 192.168.1.102 -p 6379 -a 123456
redis远程链接失败总结
①看看redis-server指向的配置文件是否指定对了
②conf配置
#bind
protected-mode no
③关闭centOS的防火墙
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动

1,设置key的过期时间
persist【O(1)】:PERSIST key【移除给定key的生存时间】
expire【O(1)】:EXPIRE key seconds【设置key的过期时间,单位秒】
pexpire【O(1)】:PEXPIRE key milliseconds【设置key的过期时间,单位毫秒】
expireat【O(1)】:EXPIREAT key timestamp【设置key的过期时间,单位时间戳】

2,Redis配置

①maxmemory设置最大内存空间(默认注释)

②maxmemory-policy最大内存空间策略(默认注释)

策略:

# volatile-lru -> 删除使用LRU算法设置过期的key
# allkeys-lru ->根据LRU算法删除任何key
# volatile-random -> 删除过期集合的key
# allkeys-random ->删除一个随机key,任何key
# volatile-ttl ->删除最接近过期时间的key
# noeviction -> 如果内存写满,则抛异常

lru :最久未使用的 

三、StackExchange.Redis

wireshark 网络封包分析软件

nuget StackExchange.Redis

public static class RedisCache
    {
        private static ConnectionMultiplexer connection;
        private static IDatabase database;

        static RedisCache()
        {
            var options=new ConfigurationOptions()
            {
                Password = "123456",
                EndPoints = { { "192.168.1.101", 6379 } }
            };
            connection = ConnectionMultiplexer.Connect(options);
            database = connection.GetDatabase();
        }
        public static void Set(string key,string str)
        {
            database.StringSet(key, str);
        }
        public static string Get(string key)
        {
           return database.StringGet(key);
        }
    }
RedisCache

https://stackexchange.github.io/StackExchange.Redis/Configuration

四、四大结构体

1,RedisServer struct

2,RedisDb struct 标识一个db,config配置默认为16个RedisDb 

3,RedisObject struct 也就是对象化的数据结构表示

4,SDS struct char[] 一个包装类(存放字符串)

 

五、Redis数据结构之String

1,get/set 命令(时间复杂度O(1))

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

  • EX seconds – 设置键key的过期时间,单位时秒
  • PX milliseconds – 设置键key的过期时间,单位时毫秒
  • NX – 只有键key不存在的时候才会设置key的值
  • XX – 只有键key存在的时候才会设置key的值
案例:使用分布式锁
set a a NX
业务操作
del a

2,incr/decr/incrby/decrby

incr 自增加1(i++)

decr自增减1(i--)

incrby自增加n(i=i+n)

decrby自增减n(i=i-n)

如果存放string中的value是int,则内存使用int存储值

3,ttl key 查询key还有多长时间过期(-2 表示过期)

4,PSETEX/SETEX 

PSETEX key milliseconds value
SETEX key seconds value
PSETEX和SETEX一样,唯一的区别是到期时间以毫秒为单位,而不是秒。

六、Redis数据结构之List

双向链表

可以用作队列(lpush/rpop、rpush/lpop)或者栈(lpush/lpop、rpush/rpop)

一般用作队列

lpush:LPUSH key value [value ...]【将所有指定的值插入到存于 key 的列表的头部。如果 key 不存在,那么在进行 push 操作前会创建一个空列表】

lpop:LPOP key【移除并且返回 key 对应的 list 的第一个元素】

rpush:RPUSH key value [value ...]【向存于 key 的列表的尾部插入所有指定的值。如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作】

rpop:RPOP key【移除并返回存于 key 的 list 的最后一个元素】

llen:LLEN key【返回存储在 key 里的list的长度。 如果 key 不存在,那么就被看作是空list,并且返回长度为 0】

blpop:BLPOP key [key ...] timeout【弹出最前面的值,如果列表中没有值,会阻塞】
brpop:BRPOP key [key ...] timeout【弹出最后面的值,如果列表中没有值,会阻塞】
注:timeout:等待时间,单位秒。0:标识永久等待
lrange:LRANGE key start stop【返回存储在 key 的列表里指定范围内的元素】
注:start stop位数组的下标

linsert:LINSERT key BEFORE|AFTER pivot value【把 value 插入存于 key 的列表中在基准值 pivot 的前面或后面】
注:BEFORE为之前/AFTER为之后
pivot:list中的值

七、Redis数据结构之Hash表

hget:HGET key field【返回 key 指定的哈希集中该字段所关联的值】
hset:HSET key field value
设置 key 指定的哈希集中指定字段的值。
如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。
如果字段在哈希集中存在,它将被重写。
field:字典中的key
value:字典中的value

hdel:HDEL key field [field ...]【从 key 指定的哈希集中移除指定的域】
hexists:HEXISTS key field【返回hash里面field是否存在】
hgetall:HGETALL key【返回 key 指定的哈希集中所有的字段和值】
hkeys:HKEYS key【返回 key 指定的哈希集中所有字段的名字】
hlen:HLEN key【返回 key 指定的哈希集包含的字段的数量】
hmget:HMGET key field [field ...]【返回 key 指定的哈希集中指定字段的值】
hmset:HMSET key field value [field value ...]【设置 key 指定的哈希集中指定字段的值】
hvals:HVALS key【返回 key 指定的哈希集中所有字段的值】

八、Redis数据结构之Set

无value的字典

sadd【O(N)】:SADD key member [member ...]【添加一个或多个指定的member元素到集合的 key中】
scard【O(1)】:SCARD key【返回集合存储的key的基数 (集合元素的数量)】
sismember【O(1)】:SISMEMBER key member【检查成员member是否存在集合中】
smembers【O(N)】:SMEMBERS key【返回key集合所有的元素】
spop【O(1)】:SPOP key [count]【随机从集合弹出count(默认1)个值】
srem【O(N)】:SREM key member [member ...]【在key集合中移除指定的元素】

差集、交集、并集
sdiff【O(N)】:SDIFF key [key ...]【差集】
sdiffstore【O(N)】:SDIFFSTORE destination key [key ...]【将差集保存到destination中】
sinter【O(N*M)】:SINTER key [key ...]【交集】
sinterstore【O(N*M)】:SINTERSTORE destination key [key ...]【将交集保存到destination中】
sunion【O(N)】:SUNION key [key ...]【并集】
sunionstore【O(N)】:SUNIONSTORE destination key [key ...]【将并集保存到destination中】

九、Redis数据结构之sorted_set

一般用做优先级队列

zadd【O(log(N))】:ZADD key [NX|XX] [CH] [INCR] score member [score member ...]【将所有指定成员添加到键为key有序集合(sorted set)里面】
XX: 仅仅更新存在的成员,不添加新成员。
NX: 不更新存在的成员。只添加新成员。
CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内。注:在通常情况下,ZADD返回值只计算新添加成员的数量。
INCR: 当ZADD指定这个选项时,成员的操作就等同ZINCRBY命令,对成员的分数进行递增操作。
zcard【O(1)】:ZCARD key【返回key的有序集元素个数】
zrange【O(log(N)+M)】:ZRANGE key start stop [WITHSCORES]【从小到大排序。显示字典信息(WITHSCORES 显示出key)】【例如:zrange sdic 0 -1 withscores】
zrevrange【O(log(N)+M)】:ZREVRANGE key start stop [WITHSCORES]【从大到小排序。显示字典信息(WITHSCORES 显示出key)】【例如:zrevrange sdic 0 -1 withscores】
zremrangebyrank【O(log(N)+M)】:ZREMRANGEBYRANK key start stop【移除有序集key中】
0:最小
-1:最大
-2:第二大。。以此类推

十、Redis数据结构之hyperloglog

等于distinct+count
计算不是100%准确
使用场景:计算某一天独立ip访问数量
pfadd 20180125 192.168.1.1 192.168.1.1 192.168.1.2【O(1)】
pfcount 20180125【O(1)】

十一、Transactions

multi:开启一个事务
exec:提交事务
discard:回滚事务

watch【乐观锁】:WATCH key [key ...]

例如客户端1watch username并开启了一个事务。当在另一个客户端2修改了username值的时候。客户端1事务exec会执行失败(回滚)

十二、发布/订阅

subscribe:SUBSCRIBE channel [channel ...]【订阅频道】
publish:PUBLISH channel message【发布消息】

 psubscribe:PSUBSCRIBE pattern [pattern ...]【订阅给定的模式的频道】

十三、redis驱动批量执行命令

        static void Main(string[] args)
        {
            var con= ConnectionMultiplexer.Connect("192.168.1.102:6379");
            var db = con.GetDatabase();

            var batch= db.CreateBatch();

            batch.SetAddAsync("username", "hunter");
            batch.ListInsertBeforeAsync("list", "1", "2");
            batch.HashSetAsync("dic", "username", "jack");
            batch.Execute();
            Console.ReadKey();
        }

十四、Redis使用Lua

Lua工具下载地址:LuaForWindows_v5.1.4-46.exe

1,命令
EVAL script numkeys key [key ...] arg [arg ...]
script:指定lua脚本的路径。或者直接写lua脚本
numkeys:制定参数的个数
key:在脚本中使用到的key(KEYS 全局key集合。单项:KEYS[1])
arg:在脚本中使用到的arg(ARGV 全局arg集合。单项:ARGV[1])
注:KEYS[0]或者ARGV[0]是错误的写法

2,Lua脚本调用Redis
redis.call('set','foo','bar')
redis.pcall('hset','dic','key','value')
redis.call() 与 redis.pcall()很类似, 他们唯一的区别是当redis命令执行结果返回错误时,
redis.call()将返回给调用者一个错误,而redis.pcall()会将捕获的错误以Lua表的形式返回

3,案例
①直接嵌入lua脚本

> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

②调用独立的lua脚本

return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}
lua文件
redis-cli --eval C:UsersHunter2DesktopLua	ext.lua a b , a b
1) "key1"
2) "key2"
3) "first"
4) "second"

③更高级的调用

需求:输入的参数在集合中存在,则打印出来

local key=KEYS[1]
local args=ARGV

local result={}
local list=redis.call("smembers",key)
for m,n in ipairs(args) do
    local exists= redis.call("sismember",key,n)
    if(exists==1)then
    table.insert(result,n)
    end
end
return result
Lua文件
C:WINDOWSsystem32>redis-cli --eval C:UsersHunter2DesktopLua	ext.lua list , 1 2 3 10
1) "1"
2) "2"
3) "3"

注:逗号分割key和agrv 

十五、Redis两种持久化方式

1,rds(默认)
快照模式,定时保存。如果重启有可能会丢失部分数据

配置信息:

强制持久化命令:save(客户端阻塞)或者bgsave(会开启一个进程执行)

2,aof

来一条命令则保存一次,aof文件保存的是文本协议

开启方式 

①注销save

②appendonly设置为yes

 

三种写入模式:

#appendfsync always:来一条保存一条,强制保存到硬盘【安全性高,性能差】
appendfsync everysec:1秒强制保存到硬盘一次【折中方案】
#appendfsync no:来一条保存一条,只保存到系统的缓冲期,至于保存到硬盘是有系统决定【安全性差,性能高】

十六、搭建Redis主-备(mster-slave)

1,配置mster-slave
配置文件# slaveof <masterip> <masterport>配置主机地址
例如:slaveof 192.168.1.102 6379
如果主redis有密码需要配置# masterauth <master-password>
info 查看redis信息

注:一旦redis服务器被设置为slave,则该redis不能写入了。只能从master中写入

2,c#中使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var con= ConnectionMultiplexer.Connect("192.168.1.102:6379,192.168.1.103:6379");
            var db = con.GetDatabase();

            db.StringAppendAsync("password", "123456");//会使用主redis
            var p = db.StringGetAsync("password").Result;//会使用备redis

            Console.WriteLine(p);
            Console.ReadKey();
        }
    }
}
c#端调用

注:如果主redis挂了,则写入会失败。可以查询

十七、搭建Redis主-备(mster-slave)+哨兵(sentinel)

sentinel监视redis主备,当主redis挂了,sentinel自动让一个slave变为master。
当原来master恢复之后,原来master恢复已经成为slave了

1,架构sentinel

例如在一台centos上建立三个哨兵

这三个哨兵会监视一个master,当有2个哨兵主观认为master挂了,则sentinel自动让一个slave变为master

主redis:192.168.1.102:6379

备redis:192.168.1.103:6379

主redis未挂时,备redis的状态:

主redis挂了,备redis的状态:

sentinel案例下载:https://pan.baidu.com/s/1ggvCu47

1,配置具体的sentinel

①拷贝redis-sentinel程序和sentinel.conf配置文件到s1、s2、s3文件中

②配置sentinel.conf

port 26379  #设置sentinel的端口

protected-mode no #将protected-mode设置为no

sentinel monitor <master-name> <ip> <redis-port> <quorum> #设置监控的master

master-name:设置主redis 的名称,随便写

ip:主redis 的ip地址

redis-port:主redis的端口号

quorum:当主观认为master挂掉的哨兵达到2个时,则客观认为master挂了。需要切换master了

例:sentinel monitor mymaster 192.168.1.102 6379 2

sentinel auth-pass <master-name> <password> #如果master设置了密码,则需要配置master的密码

例:sentinel auth-pass mymaster 123456

sentinel down-after-milliseconds mymaster 30000 #master30秒没响应,则主观认为master挂了

③启动sentinel

进入放置sentinel的文件夹

执行命令./redis-sentinel ./sentinel.conf 启动sentinel

注意:在同一系统下运行多个sentinel,sentinel的端口号不要重复

十八、 web监控【redislive】

python写的一个web监控

1,安装redislive

①首先需要安装pip(python的安装工具包pip-9.0.1.tar.gz)【相当于nuget】
下载地址:https://pypi.python.org/pypi/pip

网速慢可以下载:https://pan.baidu.com/s/1qZezffm

拷贝到centos的usr文件下,解压,进入解压文件中
python setup.py install 安装

②安装tornado【相当于iis】
pip install tornado --upgrade

③安装redis.py 【python redis驱动,相当于.net StackExchange】
pip install redis

④安装python-dateutil 【类库,相当于dll】
pip install python-dateutil --upgrade 强制更新到最新

⑤获取redislive的源代码
https://github.com/nkrode/RedisLive
解压放到centos的usr文件下。进入文件夹
将redis-live.conf.example改为redis-live.conf

redis-live.conf配置文件解析:
RedisServers:监控的RedisServers的服务器地址和端口
DataStoreType:存储类型(redis或者Sqlite存储,默认redis)
RedisStatsServer:配置存储redis的服务器地址和端口
{
    "RedisServers":
    [ 
        {
              "server": "192.168.1.103",
              "port" : 6379
        }        
    ],

    "DataStoreType" : "redis",

    "RedisStatsServer":
    {
        "server" : "192.168.1.103",
        "port" : 6379
    },
    
    "SqliteStatsStore" :
    {
        "path":  "to your sql lite file"
    }
}
配置案例

⑥开启监控脚本:./redis-monitor.py --duration=120【duration=120 默认采集二分钟】

⑦开启web站点:./redis-live.py

⑧访问
http://localhost:8888/index.html
http://192.168.1.103:8888/index.html

十九、 搭建cluster(集群)

参考文档:http://www.redis.cn/topics/cluster-tutorial.html

可能出现各种依赖问题请参考:
https://www.cnblogs.com/carryping/p/7447823.html
http://blog.csdn.net/Hello_World_QWP/article/details/78260684
http://blog.csdn.net/hello_world_qwp/article/details/78261618

1,开启cluster(集群)模式
配置文件:
cluster-enabled yes 开启集群
cluster-config-file nodes-6379.conf 集群节点文件

2,redis src下找到redis-trib.rb
①安装ruby环境:yum install ruby

②ruby的redis驱动:gem install redis
③rubygems安装:yum install -y rubygems

④通过第三方工具进行安装
./redis-trib.rb create --replicas 1 192.168.1.103:6379 192.168.1.103:6380 192.168.1.103:6381 192.168.1.103:6382

cluster nodes 查看集群
redis-cli -c 使用这种redis-cli的开启方式

3,c#驱动访问方式:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var con= ConnectionMultiplexer.Connect("192.168.1.103:6379,192.168.1.103:6380,192.168.1.103:6381,192.168.1.103:6382");
            var db = con.GetDatabase();

            db.StringSet("cc", "123456");//会使用主redis
            var p = db.StringGetAsync("cc").Result;//会使用备redis

            Console.WriteLine(p);
            Console.ReadKey();
        }
    }
}
View Code

升级完ruby需要重启

注意:

>>>创建群集
***错误:集群创建的配置无效。
*** Redis群集至少需要3个主节点。
***对于每个节点3个节点和1个副本,这是不可能的。
***至少需要6个节点。

原文地址:https://www.cnblogs.com/zd1994/p/8321509.html