--启动redis服务
E:\redis>redis-server.exe redis.windows.conf
--结束redis服务
127.0.0.1:6379> shutdown
not connected>
3.1、运行中使用config set
命令修改
--连接redis,-h <ip> -a <pwd>
E:\redis>redis-cli.exe -h 127.0.0.1
--测试redis是否正常工作
127.0.0.1:6379> ping pong
"pong"
--设置密码为xxx,服务器在外网还是设置上吧,貌似有不少公司都不设置
127.0.0.1:6379> config set requirepass 123
OK
--获取密码的时候就提示没权限了
127.0.0.1:6379> config get requirepass
(error) NOAUTH Authentication required.
--使用auth命令认证
127.0.0.1:6379> auth 123
OK
127.0.0.1:6379> config get save
1) "save"
2) "jd 900 jd 300 jd 60"
--清空持久化,只做缓存处理的话关闭(尤其配置低的服务器),持久化一次redis就可能无响应了,日志文件也不会记录
127.0.0.1:6379> config set save ""
OK
--保存创建rdb备份文件,redis:DB saved on disk
127.0.0.1:6379> save
OK
--后台save,redis:*Background saving started by pid 1968 # fork operation complete* Background saving terminated with success
127.0.0.1:6379> bgsave
Background saving started
--获取rdb文件路径,恢复备份直接覆盖重启redis即可
127.0.0.1:6379> config get dir
1) "dir"
2) "E:\\redis"
3.2、redis.windows.conf
用记事本打开直接修改保存。
##普通##
port 6379 --redis的监听端口
tcp-backlog 511 --默认就好
timeout 0 --客户端连接空闲几秒钟后关闭,0为禁用不关闭
tcp-keepalive 0 --向客户端发送ACK的时间隔(单位/秒),0为不发送
loglevel notice --记录日志级别(debug、verbose、notice、warning)
logfile "redis-log.txt" --日志文件名,为空就是输出控制台,指定文件启动后会写入文件中
syslog-enabled no --是否启动windows事件日志
syslog-ident redis --标注事件来源是redis
databases 16 --数据库数量
##快照##
save --在指定秒数和数据变化次数后保存到磁盘,不需持久化注释即可
stop-writes-on-bgsave-error yes --停止-写入-在-后台写入-错误时 yes or no,字面意思
rdbcompression yes --压缩redis的rdb数据文件?
rdbchecksum yes --rdb校验,性能消耗10%,需提高性能时可跳过
dbfilename dump.rdb --持久化的数据文件名
dir ./ --工作目录,conf和exe同文件夹
##主从##
slaveof --从库,通过主库ip、端口备份
masterauth --主库连接密码
slave-serve-stale-data yes --与主库失去连接时,是否允许客户端获取数据?
slave-read-only yes --从库只读?
repl-diskless-sync no --启动无盘复制?磁盘读写差并且带宽高 yes
repl-diskless-sync-delay 5 --无盘同步延迟秒数
repl-ping-slave-period 10 --向主库发送ping请求间隔秒数
repl-timeout 60 --ping超时
repl-disable-tcp-nodelay no --延迟将会减少但要使用更多的带宽?
repl-backlog-size 1mb --同步backlog增量
repl-backlog-ttl 3600 --backlog缓冲释放秒数,0为不释放
slave-priority 100 --当主库不工作时,提升从库为主库的优先级
min-slaves-to-write 3 --最小几个延迟
min-slaves-max-lag 10 --最小延迟秒数
##安全##
requirepass --密码
rename-command CONFIG "" --重命名命令
##LIMITS##
maxclients 10000 --最大连接数
maxheap --fork()持久化时映射文件的最大数
heapdir --堆内存映射的本地路径
persistence-available [(yes)|no] --是否关闭所有持久化
maxmemory --最大内存
maxmemory-policy volatile-lru --内存极致时,根据哪种机制删除key
maxmemory-samples 3 --样本key的个数,从中删除最旧的
##追加模式##
appendonly no --如果AOF开启,那么在启动时Redis将加载AOF文件
appendfsync everysec
--no:不要立刻刷,只有在操作系统需要刷的时候再刷。比较快。
--always:每次写操作都立刻写入到aof文件。慢,但是最安全。
--everysec:每秒写一次。折中方案。
no-appendfsync-on-rewrite no --这个设置成"yes"带来了延迟问题,就保持"no",这是保存持久数据的最安全的方式
auto-aof-rewrite-percentage 100 --超过百分比 触发重新操作
auto-aof-rewrite-min-size 64mb --设置被重新日志的最小尺寸
aof-load-truncated yes --AOF文件被发现坏损,redis将拒绝访问终止?
##LUA SCRIPTING##
lua-time-limit 5000 --脚本的最大执行时间,毫秒为单位
SLOW LOG#
slowlog-log-slower-than 10000 --记录慢查询超时时长 单位微秒
slowlog-max-len 128 --慢查询日志长度
##LATENCY MONITOR##
latency-monitor-threshold 0 --延迟控制阀数值 毫秒
Event notification
notify-keyspace-events "" --通知 Pub/Sub 客户端关于键空间发生的事件
##ADVANCED CONFIG##
--当hash只有少量的entry时,并且最大的entry所占空间没有超过指定的限制时,会用一种节省内存的数据结构来编码。可以通过下面的指令来设定限制
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
--与hash似,数据元素较少的list,可以用另一种方式来编码从而节省大量空间。这种特殊的方式只有在符合下面限制时才可以用:
list-max-ziplist-entries 512
list-max-ziplist-value 64
--set有一种特殊编码的情况:当set数据全是十进制64位有符号整型数字构成的字符串时。下面这个配置项就是用来设置set使用这种编码来节省内存的最大长度。
set-max-intset-entries 512
--与hash和list相似,有序集合也可以用一种特别的编码方式来节省大量空间。这种编码只适合长度和元素都小于下面限制的有序集合:
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
--HyperLogLog稀疏表示字节的限制。限制包括16字节的头。当HyperLogLog使用稀疏表示十字架此限制,它被转换成致密表示。16000更大的值是完全无用的,因为在这一点上密集的表示是更多的内存效率。的建议值是〜3000,以便具有的优点空间高效的编码,而不会减慢太多PFADD,这是O(N)与稀疏编码。该值可提高到〜10000时CPU不是一个问题,但空间,并且该数据集是由许多HyperLogLogs与在基数0 - 15000的范围。
hll-sparse-max-bytes 3000
--对延迟比较在意,不能够接受Redis时不时的对请求有2毫秒的延迟的话,就用"activerehashing no",如果不太在意延迟而希望尽快释放内存就设置"activerehashing yes"
activerehashing yes
--范围是1到500之间,但是值超过100通常不是一个好主意。大多数用户应该使用10这个默认值,只有在非常低的延迟要求时有必要提高到100。
hz 10
--当一个子进程重写AOF文件时,如果启用下面的选项,则文件每生成32M数据会被同步。为了增量式的写入硬盘并且避免大的延迟高峰这个指令是非常有用的
aof-rewrite-incremental-fsync yes
redis
之数据格式1、redis
数据类型
--字符串
--Redis字符串是字节序列。Redis字符串是二进制安全的,这意味着他们有一个已知的长度没有任何特殊字符终止,所以你可以存储任何东西,512兆为上限。
127.0.0.1:6379> set mykey "redis"
OK
127.0.0.1:6379> get mykey
"redis"
--哈希
--Redis的哈希是键值对的集合。 Redis的哈希值是字符串字段和字符串值之间的映射,因此它们被用来表示对象
127.0.0.1:6379> hmset user:1 uname "lily" key1 value1 key2 value2
OK
127.0.0.1:6379> hgetall user:1
1) "uname"
2) "lily"
3) "key1"
4) "value1"
5) "key2"
6) "value2"
--列表
--LPUSH 命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE 命令可从list中取出一定范围的元素
127.0.0.1:6379> rpush mylist a
(integer) 2
127.0.0.1:6379> rpush mylist b
(integer) 3
127.0.0.1:6379> lpush mylist c
(integer) 4
127.0.0.1:6379> lrange mylist 1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange mylist 0 1
1) "c"
2) "123"
127.0.0.1:6379>
--集合
--Redis的集合是字符串的无序集合。在Redis您可以添加,删除和测试文件是否存在,在成员O(1)的时间复杂度
127.0.0.1:6379> sadd myset 1 2 3 4
(integer) 4
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
4) "4"
--有序集合
--Redis的有序集合类似于Redis的集合,字符串不重复的集合。不同的是,一个有序集合的每个成员用分数,以便采取有序set命令,从最小的到最大的成员分数有关。虽然成员具有唯一性,但分数可能会重复
127.0.0.1:6379> zadd myzset 0 "an"
(integer) 1
127.0.0.1:6379> zadd myzset 1 "kc" 2 "bi"
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "an"
2) "kc"
3) "bi"
--bit
--与sqlserver bit类型类似,存储0 1值
127.0.0.1:6379> set bitkey 0
OK
127.0.0.1:6379> set bitkey1 1
OK
127.0.0.1:6379> get bitkey
"0"
--HyperLogLog
--Redis 在 2.8.9 版本添加了 HyperLogLog 结构。
--Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
--在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
--但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
127.0.0.1:6379> pfadd hllkey "c sharp" "c++" "java" "object-c"
(integer) 1
127.0.0.1:6379> pfcount hllkey
(integer) 4
--GEOADD
--将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作
--该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:
----有效的经度从-180度到180度。
----有效的纬度从-85.05112878度到85.05112878度。
--当坐标位置超出上述指定范围时,该命令将会返回一个错误。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
Redis
之事物--开启一个事物
127.0.0.1:6379> multi
OK
--操作不会立即执行,会被放入事物队列中
127.0.0.1:6379> set stringkey1 one
QUEUED
127.0.0.1:6379> set stringkey2 two
QUEUED
127.0.0.1:6379> set stringkey3 three
QUEUED
--通过exec执行,可通过discard清空事物队列中等待执行的操作,放弃执行事务
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
redis
之StackExchange
虽然ServiceStack
从v4
开始就变成商业版本了,不妨还有大量的公司在使用,但是相关的文章大家已经写烂了,所以就来写写另外一个用于NET
访问Redis
的Client--StackExchange
。当然也有不少人对它的稳定性、性能方面持有顾虑,我还没有使用它的大数据项目经验,但是Microsoft.Web.RedisSessionStateProvider
库底层都基于StackExchange
访问Redis
处理web session
的分布式存储了,那我们也不需要过多的纠结了,兵来将挡水来土掩。
感受MS
提供的分布式存储session
,戳此链接:http://www.cnblogs.com/NotAnEmpty/p/5459977.html
安装:
PM> Install-Package StackExchange.Redis
//1.1 Connect
//使用连接字符串或者ConfigurationOptions对象连接redis,作者把ConnectionMultiplexer设计为共享和重用,并且线程安全,所以共用一个实例就可以了
string connstr = "127.0.0.1:6379,allowadmin=true";
ConnectionMultiplexer conn = ConnectionMultiplexer.Connect(connstr);
ConfigurationOptions options = ConfigurationOptions.Parse(connstr);
string parsestr = options.ToString();
//ConnectionMultiplexer conn = ConnectionMultiplexer.Connect(new ConfigurationOptions() {
// EndPoints = { "127.0.0.1:6379" }
//});
//1.2 GetDatabase
//通过GetDatabase(int db = -1, object asyncState = null)穿入数据库ID获取数据库对象,异步操作需传入Task.AsyncState
IDatabase db = conn.GetDatabase(0);
ConfigurationOptions by translate.google
string
//2.1.1 set
//key-val存储
//bool StringSet(RedisKey key, RedisValue value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags flags = CommandFlags.None);
bool stringsetResult = db.StringSet("mykey", "myvalue", TimeSpan.FromHours(1), When.Always, CommandFlags.None);
//key-val组存储
//bool StringSet(KeyValuePair[] values, When when = When.Always, CommandFlags flags = CommandFlags.None);
db.StringSet(new KeyValuePair<RedisKey, RedisValue>[] { new KeyValuePair<RedisKey, RedisValue>("mykey", "myvalue") });
//追加值,返回追加后长度
//long StringAppend(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
long appendlong = db.StringAppend("mykey", "|myvalue");
//偏移量存储
//RedisValue StringSetRange(RedisKey key, long offset, RedisValue value, CommandFlags flags = CommandFlags.None);
db.StringSetRange("myrangekey", 3, "myrangevalue"); //值:___myrangevalue
//增量存储,与StringDecrement相反
//long StringIncrement(RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None);
//double StringIncrement(RedisKey key, double value, CommandFlags flags = CommandFlags.None);
db.StringSet("intkey", 10);
db.StringIncrement("intkey", 2); //value:12
//2.1.2 get
//根据key获取val
//RedisValue StringGet(RedisKey key, CommandFlags flags = CommandFlags.None);
RedisValue rvalue = db.StringGet("mykey");
//rvalue.IsNull 是否null
//获取一组val
//RedisValue[] StringGet(RedisKey[] keys, CommandFlags flags = CommandFlags.None);
RedisValue[] rvalues = db.StringGet(new RedisKey[] { "mykey" });
//把存储的string substring后返回
//RedisValue StringGetRange(RedisKey key, long start, long end, CommandFlags flags = CommandFlags.None);
RedisValue rangevalue = db.StringGetRange("mykey", 0, 1); //返回my
//存储新值,返回旧值
//RedisValue StringGetSet(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
RedisValue oldval = db.StringGetSet("key1", "val2");
//2.1.3 other
//获取带有过期时间的val
//RedisValueWithExpiry StringGetWithExpiry(RedisKey key, CommandFlags flags = CommandFlags.None);
RedisValueWithExpiry rvalwithxp = db.StringGetWithExpiry("mykey");
//获取length
//long StringLength(RedisKey key, CommandFlags flags = CommandFlags.None);
long vallength = db.StringLength("mykey");
hash
//2.1.1 set
//bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None);
db.HashSet("hashkey1", "name", "lily");
//void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None);
db.HashSet("hashkey2", new HashEntry[] { new HashEntry("name", "lucy"), new HashEntry("age", 18) });
//2.1.2 get
//RedisValue HashGet(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None);
RedisValue rhashval = db.HashGet("hashkey1", "name");
//RedisValue[] HashGet(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None);
RedisValue[] rhashvals = db.HashGet("hashkey2", new RedisValue[] { "name", "age" });
//HashEntry[] HashGetAll(RedisKey key, CommandFlags flags = CommandFlags.None);
HashEntry[] hashentitrys = db.HashGetAll("hashkey2");
//long HashIncrement(RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None);
//double HashIncrement(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None);
db.HashIncrement("hashkey2", "age", 3);
//2.1.3 other
//key所对应的hash字段是否存在
//bool HashExists(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None);
db.HashExists("hashkey1", "name");
//key所对应的hash字段个数
//long HashLength(RedisKey key, CommandFlags flags = CommandFlags.None);
db.HashLength("hashkey1");
//key所对应的所有hash字段
//RedisValue[] HashKeys(RedisKey key, CommandFlags flags = CommandFlags.None);
db.HashKeys("hashkey2");
//根据pattern(pattern参考:http://redis.io/commands/keys)扫描key所对应的字段值,可指定扫描页数、开始和偏移量
//IEnumerable HashScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags);
db.HashScan("hashkey2");
foreach (HashEntry item in db.HashScan("hashkey2","age",10))
{
Console.WriteLine("{0}:{1}", item.Name, item.Value);
}
//删除,返回 true/false 或者 删除字段值的个数
//bool HashDelete(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None);
db.HashDelete("hashkey1", "name");
//long HashDelete(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None);
db.HashDelete("hashkey2", new RedisValue[] { "name", "age" });
list
//2.3.1 push
//从头部入列
//long ListLeftPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None);
db.ListLeftPush("listkey1", "top");
//入列多个,top1在最上
//long ListLeftPush(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);
db.ListLeftPush("listkey1", new RedisValue[] { "top3", "top1" });
//从尾部入列
//long ListRightPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None);
db.ListRightPush("listkey1", "bottom");
//入列多个,buttom3在最下
//long ListRightPush(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);
db.ListRightPush("listkey1", new RedisValue[] { "bottom1", "bottom3" });
//在xx之后入列
//long ListInsertAfter(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None);
db.ListInsertAfter("listkey1", "top1", "top2");
//在xx之前入列
//long ListInsertBefore(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None);
db.ListInsertBefore("listkey1", "bottom3", "bottom2");
//从第几个后面入列,第4个为top(top1 top2 top3 top bottom bottom1 bottom2 bottom3)
//void ListSetByIndex(RedisKey key, long index, RedisValue value, CommandFlags flags = CommandFlags.None);
db.ListSetByIndex("listkey1", 4, "middle");
//2.3.2 pop
//从上出列 top1
//RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.None);
db.ListLeftPop("listkey1");
//从下出列 bottom3
//RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.None);
db.ListRightPop("listkey1");
//根据index获取(下标0开始) 3为middle,之前从上出列了一个top1
//RedisValue ListGetByIndex(RedisKey key, long index, CommandFlags flags = CommandFlags.None);
db.ListGetByIndex("listkey1", 3);
//获取range
//RedisValue[] ListRange(RedisKey key, long start = 0, long stop = -1, CommandFlags flags = CommandFlags.None);
foreach (RedisValue item in db.ListRange("listkey1", 0, 3))
{
Console.WriteLine(item);
}
//2.3.2 other
//获取list的length
//long ListLength(RedisKey key, CommandFlags flags = CommandFlags.None);
db.ListLength("listkey1");
//截取范围保留
//void ListTrim(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None);
db.ListTrim("listkey1", 3, 4);
//删除,返回删除成功个数
//long ListRemove(RedisKey key, RedisValue value, long count = 0, CommandFlags flags = CommandFlags.None);
db.ListRemove("listkey1", "middle");
set
//2.4.1 add
//如果value重复,将被忽略不添加
//bool SetAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
db.SetAdd("setkey", 1);
//long SetAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);
db.SetAdd("setkey", new RedisValue[] { 1, 2, 3, 4, 5 });
db.SetAdd("setkey2", new RedisValue[] { 5, 6, 7, 8 });
//2.4.2 get
//获取集合内所有元素
//RedisValue[] SetMembers(RedisKey key, CommandFlags flags = CommandFlags.None);
RedisValue[] vals = db.SetMembers("setkey2");
//2.4.3 remove
//移除单个val
//long SetRemove(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);
db.SetRemove("setkey2", 7);
//移除多个val,返回成功个数
//bool SetRemove(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
db.SetRemove("setkey2", new RedisValue[] { 7, 8 });
//2.4.4 Combine
//对两个集合合并操作
//RedisValue[] SetCombine(SetOperation operation, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None);
var keyvals = db.SetCombine(SetOperation.Union, "setkey", "setkey2");
Console.WriteLine(string.Join(",", keyvals));
//RedisValue[] SetCombine(SetOperation operation, RedisKey[] keys, CommandFlags flags = CommandFlags.None);
db.SetCombine(SetOperation.Union, new RedisKey[] { "setkey", "setkey2" });
//合并后返回
//long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None);
RedisValue[] rvals = db.SetCombine(SetOperation.Union, "setkey", "setkey2");
//合并后直存储,,返回val的数量
//long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None);
db.SetCombineAndStore(SetOperation.Union, "setkeycombine", new RedisKey[] { "setkey", "setkey2" });
Console.WriteLine(string.Join(",", db.SetMembers("setkeycombine")));
//2.4.5 other
//scan pattern参考:http://redis.io/commands/keys
//IEnumerable SetScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags);
db.SetAdd("setkey3", new RedisValue[] { "four", "one", "two", "three" });
foreach (RedisValue item in db.SetScan("setkey3", "*o*", 10, CommandFlags.None))
{
Console.WriteLine(item);
}
//是否包含该val
//bool SetContains(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
db.SetContains("setkeycombine", 7);
//集合length
//long SetLength(RedisKey key, CommandFlags flags = CommandFlags.None);
db.SetLength("setkeycombine");
//把val从一个set移动到另一个set,目标set不存在则新建
//bool SetMove(RedisKey source, RedisKey destination, RedisValue value, CommandFlags flags = CommandFlags.None);
db.SetMove("setkey", "toset", 1);
//随机移除并返回一个val
//RedisValue SetPop(RedisKey key, CommandFlags flags = CommandFlags.None);
db.SetPop("setkey");
//随机返回 但不移除,可指定返回数量
//RedisValue SetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None);
db.SetRandomMember("setkey");
//RedisValue[] SetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None);
db.SetRandomMembers("setkey", 3);
zset
//2.5.1 add 重复则忽略
//bool SortedSetAdd(RedisKey key, RedisValue member, double score, CommandFlags flags = CommandFlags.None);
db.SortedSetAdd("zsetkey", "日本", 101);
db.SortedSetAdd("zsetkey", "韩国", 102);
//long SortedSetAdd(RedisKey key, SortedSetEntry[] values, CommandFlags flags = CommandFlags.None);
db.SortedSetAdd("zsetkey1", new SortedSetEntry[] { new SortedSetEntry("巴西", 0), new SortedSetEntry("意大利", 1), new SortedSetEntry("阿根廷", 2), new SortedSetEntry("英格兰", 3), });
//2.5.2 get
//排序获取,下标从0开始
//RedisValue[] SortedSetRangeByRank(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
RedisValue[] rvals = db.SortedSetRangeByRank("newzsetkey", 0, 2, Order.Ascending, CommandFlags.None);
Console.WriteLine(string.Join(",", rvals));
//和上面一个卵用,只不过返回了SortedSetEntry数组,有了score属性
//SortedSetEntry[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
foreach (SortedSetEntry item in db.SortedSetRangeByRankWithScores("newzsetkey", 0, 2, Order.Ascending, CommandFlags.None))
{
Console.WriteLine("{0}:{1}", item.Element, item.Score);
}
//根据score获取,skip、take分页获取
//RedisValue[] SortedSetRangeByScore(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None);
RedisValue[] rvalsbyscore = db.SortedSetRangeByScore("newzsetkey", 2, 4, Exclude.None, Order.Ascending, 0, 10, CommandFlags.None);
//根据score获取,带score属性
//SortedSetEntry[] SortedSetRangeByScoreWithScores(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None);
SortedSetEntry[] entitys = db.SortedSetRangeByScoreWithScores("newzsetkey", 2, 4, Exclude.None, Order.Ascending, 0, 10, CommandFlags.None);
//在同一score的zset中获取一定范围的元素
//RedisValue[] SortedSetRangeByValue(RedisKey key, RedisValue min = default(RedisValue), RedisValue max = default(RedisValue), Exclude exclude = Exclude.None, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None);
RedisValue[] rvalsbyval = db.SortedSetRangeByValue("newzsetkey", 2, 4, Exclude.None, 0, 10, CommandFlags.None);
//返回元素的score,不存在返回0
//double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None);
db.SortedSetScore("zsetkey1", "美国");
//2.5.3 del
//根据val删
//bool SortedSetRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None);
db.SortedSetRemove("zsetkey", "意大利");
//long SortedSetRemove(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None);
db.SortedSetRemove("zsetkey", new RedisValue[] { "意大利", "美国" });
//根据下标范围删
//long SortedSetRemoveRangeByRank(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None);
db.SortedSetRemoveRangeByRank("zsetkey", 0, 2);
//根据score删
//long SortedSetRemoveRangeByScore(RedisKey key, double start, double stop, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
db.SortedSetRemoveRangeByScore("zsetkey", 2, 4);
//在同一score的zset中根据下标删
//long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
db.SortedSetRemoveRangeByValue("zsetkey", 2, 4);
//2.5.4 combine
//合并操作 返回集合个数
//long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);
db.SortedSetCombineAndStore(SetOperation.Union, "newzsetkey", "zsetkey", "zsetkey1");
//long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, double[] weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);
db.SortedSetCombineAndStore(SetOperation.Union, "newzsetkey", new RedisKey[] { "zsetkey", "zsetkey1" });
//2.5.5 other
//scan,可指定位置和偏移
//IEnumerable SortedSetScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags);
db.SortedSetScan("", "?国", 10, CommandFlags.None);
//IEnumerable SortedSetScan(RedisKey key, RedisValue pattern = default(RedisValue), int pageSize = 10, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None);
db.SortedSetScan("", "?国", 10, 0, 1, CommandFlags.None);
//排序score加等于
//double SortedSetIncrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None);
db.SortedSetIncrement("zsetkey1", "阿根廷", 6);
//排序score减等于
//double SortedSetDecrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None);
db.SortedSetDecrement("zsetkey1", "阿根廷", 5);
//获取score在这之间元素的个数
//long SortedSetLength(RedisKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
db.SortedSetLength("zsetkey1", 0, 3);
//long SortedSetLengthByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
//同一score的元素在此之间的元素个数
db.SortedSetLengthByValue("zsetkey1", 0, 2);
//val值的个数
//long? SortedSetRank(RedisKey key, RedisValue member, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
db.SortedSetRank("newzsetkey", "意大利");
HyperLogLog
//添加元素到HyperLogLog数据结构
//bool HyperLogLogAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
//bool HyperLogLogAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);
db.HyperLogLogAdd("HyperLogLogKey", "c sharp");
db.HyperLogLogAdd("HyperLogLogKey", new RedisValue[] { "c++", "java", "object-c" });
//返回指定HyperLogLog结构key上元素的近似基数
//long HyperLogLogLength(RedisKey key, CommandFlags flags = CommandFlags.None);
//long HyperLogLogLength(RedisKey[] keys, CommandFlags flags = CommandFlags.None);
Console.WriteLine(db.HyperLogLogLength("HyperLogLogKey"));
db.HyperLogLogLength(new RedisKey[] { "HyperLogLogKey", "HyperLogLogKey1" });
//合并
//void HyperLogLogMerge(RedisKey destination, RedisKey[] sourceKeys, CommandFlags flags = CommandFlags.None);
//void HyperLogLogMerge(RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None);
db.HyperLogLogMerge("newHyperLogLogKey", "HyperLogLogKey", "HyperLogLogKey1");
db.HyperLogLogMerge("newHyperLogLogKey", new RedisKey[] { "HyperLogLogKey", "HyperLogLogKey1" });
bit
// set
//bool StringSetBit(RedisKey key, long offset, bool bit, CommandFlags flags = CommandFlags.None);
db.StringSetBit("bitkey", 0, true);
// get
//bool StringGetBit(RedisKey key, long offset, CommandFlags flags = CommandFlags.None);
Console.WriteLine(db.StringGetBit("bitkey", 0));
//other
//long StringBitCount(RedisKey key, long start = 0, long end = -1, CommandFlags flags = CommandFlags.None);
Console.WriteLine(db.StringBitCount("bitkey",0,1));
//long StringBitPosition(RedisKey key, bool bit, long start = 0, long end = -1, CommandFlags flags = CommandFlags.None);
Console.WriteLine(db.StringBitPosition("bitkey",false, 0, 1));
//多key之间取与或非运算,存入新的key:destination
//long StringBitOperation(Bitwise operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None);
db.StringBitOperation(Bitwise.And, "newbitkey", new RedisKey[] { "bitkey1", "bitkey2" });
//long StringBitOperation(Bitwise operation, RedisKey destination, RedisKey first, RedisKey second = default(RedisKey), CommandFlags flags = CommandFlags.None);
db.StringBitOperation(Bitwise.And, "newbitkey", "bitkey1", "bitkey2");
key
//del 删除单个及多个key
//bool KeyDelete(RedisKey key, CommandFlags flags = CommandFlags.None);
db.KeyDelete("key1");
//long KeyDelete(RedisKey[] keys, CommandFlags flags = CommandFlags.None);
db.KeyDelete(new RedisKey[] {"key1","key2" });
//是否存在
//bool KeyExists(RedisKey key, CommandFlags flags = CommandFlags.None);
//是否过期
//bool KeyExpire(RedisKey key, TimeSpan? expiry, CommandFlags flags = CommandFlags.None);
//bool KeyExpire(RedisKey key, DateTime? expiry, CommandFlags flags = CommandFlags.None);
//序列号key 参考:http://redis.io/commands/dump
//byte[] KeyDump(RedisKey key, CommandFlags flags = CommandFlags.None);
//key的转移,保证源库上的key删除,目标库的key增加 参考:http://redis.io/commands/MIGRATE
//void KeyMigrate(RedisKey key, EndPoint toServer, int toDatabase = 0, int timeoutMilliseconds = 0, MigrateOptions migrateOptions = MigrateOptions.None, CommandFlags flags = CommandFlags.None);
//key转移到目标库 http://redis.io/commands/move
//bool KeyMove(RedisKey key, int database, CommandFlags flags = CommandFlags.None);
//删除现有的超时key http://redis.io/commands/persist
//bool KeyPersist(RedisKey key, CommandFlags flags = CommandFlags.None);
//随机返回一个key http://redis.io/commands/randomkey
//RedisKey KeyRandom(CommandFlags flags = CommandFlags.None);
//重命名key http://redis.io/commands/renamenx
//bool KeyRename(RedisKey key, RedisKey newKey, When when = When.Always, CommandFlags flags = CommandFlags.None);
//重新序列化存储key http://redis.io/commands/restore
//void KeyRestore(RedisKey key, byte[] value, TimeSpan? expiry = default(TimeSpan?), CommandFlags flags = CommandFlags.None);
//返回key还有多久到期 http://redis.io/commands/ttl
//TimeSpan? KeyTimeToLive(RedisKey key, CommandFlags flags = CommandFlags.None);
//key对应数据的类型 http://redis.io/commands/type
//RedisType KeyType(RedisKey key, CommandFlags flags = CommandFlags.None);
script
//script 核心还在redis脚本的编写 http://redis.io/commands/eval
//RedisResult ScriptEvaluate(LoadedLuaScript script, object parameters = null, CommandFlags flags = CommandFlags.None);
db.ScriptEvaluate(LuaScript.Prepare("redis.call('set', @key, @value)"), new { key = "mykey", value = "myvalue" });
//RedisResult ScriptEvaluate(LuaScript script, object parameters = null, CommandFlags flags = CommandFlags.None);
db.ScriptEvaluate(LuaScript.Prepare("redis.call('set', @key, @value)"), new { key = "mykey", value = "myvalue" });
//RedisResult ScriptEvaluate(byte[] hash, RedisKey[] keys = null, RedisValue[] values = null, CommandFlags flags = CommandFlags.None);
byte[] resbytes = new SHA1CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes("..."));
RedisResult res = db.ScriptEvaluate(resbytes, new RedisKey[] { "key1", "key2" }, new RedisValue[] { "first", "second" });
Console.WriteLine(res);
//RedisResult ScriptEvaluate(string script, RedisKey[] keys = null, RedisValue[] values = null, CommandFlags flags = CommandFlags.None);
db.ScriptEvaluate("return {key[1],key[2],argv[1],argv[2]}",
new RedisKey[] { "key1", "key2" }, new RedisValue[] { "first", "second" });
Console.ReadKey();
transaction
//db.StringSet("trankey", "yes");
//2.9.1 一个简单的列子就足够了:如果trankey的值为yes,则改为no
//开启一个事物
ITransaction tran = db.CreateTransaction();
//为事物增加一个执行的前提条件,也可以不添加
ConditionResult cr = tran.AddCondition(Condition.StringEqual("trankey", "yes"));
//注意:此处cr.WasSatisfied仍为默认值false,待执行Execute()之后才会返回真实结果,如果为true,则exec将会执行,否则rollback
//因为异步等待状态,所以无需判断
tran.StringSetAsync("trankey", "no");
//commit/rollback
bool committed = tran.Execute();
Console.WriteLine(cr.WasSatisfied);
Console.WriteLine(committed);
Task
//异步都会有Async,所以前面都没有列出来
Task<bool> t = db.StringSetAsync("asyncstringkey", "none");
//可以看到是false,因为异步线程还没有执行操作
Console.WriteLine(t.IsCompleted);
Task<bool> t1 = db.StringSetAsync("asyncstringkey1", "none1");
t1.Wait();
//等待执行完成,返回true
Console.WriteLine(t.IsCompleted);
lock
//lock主要是对一些多线程操作的处理,lock三种状态
// 键(在数据库中的锁的唯一名称)
// 值(一个调用者指示谁“拥有”该锁,并且检查释放和延长锁被正确完成)
// key的持续时间
//bool LockExtend(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None);
//RedisValue LockQuery(RedisKey key, CommandFlags flags = CommandFlags.None);
//bool LockRelease(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);
//bool LockTake(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None);
string val = DateTime.Now.ToString();
if (db.LockTake("mykey", val, TimeSpan.FromSeconds(10)))
{
try
{
//其他线程就不可以take了,等待当前线程操作完release之后。
}
finally
{
db.LockRelease("mykey", val);
}
}
消息组建中,重要的概念便是生产者,消费者,消息中间件。
ISubscriber sub = redis.GetSubscriber();
首先,先拿到一个ISubscriber
对象。在生产者端我们发布一条消息:
sub.Publish("messages", "hello");
,在消费者端得到该消息并输出
sub.Subscribe("messages", (channel, message) => {
Console.WriteLine((string)message);
});
一般使用更专业的消息队列来处理这种业务场景,因此这里就略过了。
Sync vs Async vs Fire-and-Forget
最后,这里有三种命令模式分别对应StackExchange.Redis
的三类不同的使用场景。
Sync
,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
Async
,异步模式直接走的是Task模型。
Fire-and-Forget
,就是发送命令,然后完全不关心最终什么时候完成命令操作。
db.StringIncrement(pageKey, flags: CommandFlags.FireAndForget);
这里值得注意的是,在Fire-and-Forget
模式下,所有命令都会立即得到返回值,当然该值都是该返回值类型的默认值,比如操作返回类型是bool
将会立即得到false
,因为false = default(bool)
。