分布式中使用 Redis 实现 Session 共享(上)

来源:互联网 发布:仿京东商城源码 php 编辑:程序博客网 时间:2024/06/05 10:15

上一篇介绍了如何使用nginx+iis部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是”如何解决多站点下Session共享”。这篇文章将会介绍如何使用Redis,下一篇在此基础上实现Session。

这里特别说明一下,其实没有必要使用Redis来解决Session共享。Asp.net提供了StateServer模式来共享Session,这里重复造轮子的目的1:熟悉Redis的基本知识和使用 2.学习和巩固Session的实现原理。

 

Redis安装配置

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

最新版本的redis版本为3.0.3,支持集群功能。我这下载的是window版本的,实际场景都是安装在linux系统下的。下载地址:redis-2.8.19.rar 。更多下载地址:

官网 :http://redis.io/download MSOpenTech:https://github.com/MSOpenTech/redis  dmajkic:https://github.com/dmajkic/redis/downloads
下载完成之后解压运行redis-server.exe就启动了redis了,启动后会在进程里面看到reids。

1.读写分离配置

redis的读写分离需要修改配置文件,把解压的文件复制了一份。两份文件是一样的,分别命名为MasterRedis-2.8.19(主redis服务),SlaveRedis-2.8.19(从redis服务)。redis默认绑定的是6379端口,

我们保持主服务配置不变,修改从服务配置。

  • 修改从服务绑定端口(修改时可以直接搜索port关键字)

  • 修改从服务对应的主服务地址(修改时可以直接搜索slaveof关键字)

  • 配置文件修改完成以后,分别启动主服务和从服务

从服务启动以后,主服务会发送一条同步的sync命令,同步从服务器的缓存数据。
五种数据类型使用

服务搭建好以后可以使用.net版本redis操作类库ServiceStack.Redis来操作redis,本文会用到以下三个dll。

初始化RedisClient对象

1
var client = newRedisClient("120.26.197.185", 6379);

1.String

String是最常用的一种数据类型,普通的key/value存储都可以归为此类,value其实不仅是String,也可以是数字:比如想知道什么时候封锁一个IP地址(访问超过几次)。INCRBY命令让这些变得很容易,通过原子递增保持计数。

1
2
3
4
5
6
7
8
9
10
#region "字符串类型"
client.Set<string>("name","laowang");
stringuserName = client.Get<string>("name");
Console.WriteLine(userName);
//访问次数
client.Set<int>("IpAccessCount", 0);
//次数递增
client.Incr("IpAccessCount");
Console.WriteLine(client.Get<int>("IpAccessCount"));
#endregion


2.Hash

一个hashid可以存储多项信息,每一项信息也有自己的key

1
2
3
4
5
6
client.SetEntryInHash("userInfoId","name","zhangsan");
client.SetEntryInHash("userInfoId","name1","zhangsan1");
client.SetEntryInHash("userInfoId","name2","zhangsan2");
client.SetEntryInHash("userInfoId","name3","zhangsan3");
client.GetHashKeys("userInfoId").ForEach(e => Console.WriteLine(e));
client.GetHashValues("userInfoId").ForEach(e => Console.WriteLine(e));


3.List

应用场景:

  • Redis list的应用场景非常多,也是Redis最重要的数据结构之一。
  • 我们可以轻松地实现最新消息排行等功能。
  • Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#region "List类型"
 
client.AddItemToList("userInfoId1","123");
client.AddItemToList("userInfoId1","1234");
 
Console.WriteLine("List数据项条数:"+ client.GetListCount("userInfoId1"));
Console.WriteLine("List数据项第一条数据:"+ client.GetItemFromList("userInfoId1", 0));
Console.WriteLine("List所有数据");
client.GetAllItemsFromList("userInfoId1").ForEach(e => Console.WriteLine(e));
#endregion
 
#region "List类型做为队列和栈使用"
Console.WriteLine(client.GetListCount("userInfoId1"));
//队列先进先出
//Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
//Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
 
//栈后进先出
Console.WriteLine("出栈"+client.PopItemFromList("userInfoId1"));
Console.WriteLine("出栈"+client.PopItemFromList("userInfoId1"));
#endregion


4.Set

应用场景:

  • Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
  • 比如在微博应用中,每个人的好友存在一个集合(set)中,这样求两个人的共同好友的操作,可能就只需要用求交集命令即可。
  • Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
client.AddItemToSet("A","B");
client.AddItemToSet("A","C");
client.AddItemToSet("A","D");
client.AddItemToSet("A","E");
client.AddItemToSet("A","F");
 
client.AddItemToSet("B","C");
client.AddItemToSet("B","F");
 
//求差集
Console.WriteLine("A,B集合差集");
client.GetDifferencesFromSet("A","B").ToList<string>().ForEach(e => Console.Write(e + ","));
 
//求集合交集
Console.WriteLine("\nA,B集合交集");
client.GetIntersectFromSets(newstring[] { "A","B"}).ToList<string>().ForEach(e => Console.Write(e + ","));
 
//求集合并集
Console.WriteLine("\nA,B集合并集");
client.GetUnionFromSets(newstring[] { "A","B"}).ToList<string>().ForEach(e => Console.Write(e + ","));

5.Sort Set(排序)

应用场景:

  • 以某个条件为权重,比如按顶的次数排序.
  • ZREVRANGE命令可以用来按照得分来获取前100名的用户,ZRANK可以用来获取用户排名,非常直接而且操作容易。
  • Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。
  • 比如:twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
  • 比如:全班同学成绩的SortedSets,value可以是同学的学号,而score就可以是其考试得分,这样数据插入集合的,就已经进行了天然的排序。
  • 另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#region "有序Set操作"
client.AddItemToSortedSet("SA","B", 2);
client.AddItemToSortedSet("SA","C", 1);
client.AddItemToSortedSet("SA","D", 5);
client.AddItemToSortedSet("SA","E", 3);
client.AddItemToSortedSet("SA","F", 4);
 
//有序集合降序排列
Console.WriteLine("\n有序集合降序排列");
client.GetAllItemsFromSortedSetDesc("SA").ForEach(e => Console.Write(e + ","));
Console.WriteLine("\n有序集合升序序排列");
client.GetAllItemsFromSortedSet("SA").ForEach(e => Console.Write(e + ","));
 
client.AddItemToSortedSet("SB","C", 2);
client.AddItemToSortedSet("SB","F", 1);
client.AddItemToSortedSet("SB","D", 3);
 
Console.WriteLine("\n获得某个值在有序集合中的排名,按分数的升序排列");
Console.WriteLine(client.GetItemIndexInSortedSet("SB","D"));
 
Console.WriteLine("\n获得有序集合中某个值得分数");
Console.WriteLine(client.GetItemScoreInSortedSet("SB","D"));
 
Console.WriteLine("\n获得有序集合中,某个排名范围的所有值");
client.GetRangeFromSortedSet("SA", 0, 3).ForEach(e => Console.Write(e + ","));
 
#endregion

 

封装拓展

最后提供一份别人写好的Redis操作的帮助类,用到了PooledRedisClientManager连接池来获取RedisClient,同时用到了读写分离的概念,可以直接拿来使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingServiceStack.Redis;
 
namespaceCom.Redis
{
    /// <summary>
    /// 来源:http://blog.wx6.org/2013/349.htm
    /// </summary>
    publicclass RedisBase
    {
        privatestatic string[] ReadWriteHosts = System.Configuration.ConfigurationSettings.AppSettings["readWriteHosts"].Split(newchar[] { ';'});
        privatestatic string[] ReadOnlyHosts = System.Configuration.ConfigurationSettings.AppSettings["readOnlyHosts"].Split(newchar[] { ';'});
 
        #region -- 连接信息 --
        publicstatic PooledRedisClientManager prcm = CreateManager(ReadWriteHosts, ReadOnlyHosts);
 
        privatestatic PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
        {
            // 支持读写分离,均衡负载 
            returnnew PooledRedisClientManager(readWriteHosts, readOnlyHosts, newRedisClientManagerConfig
            {
                MaxWritePoolSize = 5, // “写”链接池链接数 
                MaxReadPoolSize = 5, // “读”链接池链接数 
                AutoStart = true,
            });
        }
        #endregion
 
        #region -- Item --
        /// <summary>
        /// 设置单体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        publicstatic bool Item_Set<T>(stringkey, T t)
        {
            try
            {
                using(IRedisClient redis = prcm.GetClient())
                {
                    returnredis.Set<T>(key, t, newTimeSpan(1, 0, 0));
                }
            }
            catch(Exception ex)
            {
                // LogInfo
            }
            returnfalse;
        }
 
        /// <summary>
        /// 获取单体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        publicstatic T Item_Get<T>(stringkey) where T : class
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                returnredis.Get<T>(key);
            }
        }
 
        /// <summary>
        /// 移除单体
        /// </summary>
        /// <param name="key"></param>
        publicstatic bool Item_Remove(stringkey)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                returnredis.Remove(key);
            }
        }
 
        #endregion
 
        #region -- List --
 
        publicstatic void List_Add<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
            }
        }
 
        publicstatic bool List_Remove<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                returnredisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
            }
        }
        publicstatic void List_RemoveAll<T>(stringkey)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                redisTypedClient.Lists[key].RemoveAll();
            }
        }
 
        publicstatic int List_Count(stringkey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                returnredis.GetListCount(key);
            }
        }
 
        publicstatic List<T> List_GetRange<T>(stringkey, intstart, intcount)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                var c = redis.GetTypedClient<T>();
                returnc.Lists[key].GetRange(start, start + count - 1);
            }
        }
 
        publicstatic List<T> List_GetList<T>(stringkey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                var c = redis.GetTypedClient<T>();
                returnc.Lists[key].GetRange(0, c.Lists[key].Count);
            }
        }
 
        publicstatic List<T> List_GetList<T>(stringkey, intpageIndex, intpageSize)
        {
            intstart = pageSize * (pageIndex - 1);
            returnList_GetRange<T>(key, start, pageSize);
        }
 
        /// <summary>
        /// 设置缓存过期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="datetime"></param>
        publicstatic void List_SetExpire(stringkey, DateTime datetime)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                redis.ExpireEntryAt(key, datetime);
            }
        }
        #endregion
 
        #region -- Set --
        publicstatic void Set_Add<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                redisTypedClient.Sets[key].Add(t);
            }
        }
        publicstatic bool Set_Contains<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                returnredisTypedClient.Sets[key].Contains(t);
            }
        }
        publicstatic bool Set_Remove<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                var redisTypedClient = redis.GetTypedClient<T>();
                returnredisTypedClient.Sets[key].Remove(t);
            }
        }
        #endregion
 
        #region -- Hash --
        /// <summary>
        /// 判断某个数据是否已经被缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        publicstatic bool Hash_Exist<T>(stringkey, stringdataKey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                returnredis.HashContainsEntry(key, dataKey);
            }
        }
 
        /// <summary>
        /// 存储数据到hash表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        publicstatic bool Hash_Set<T>(stringkey, stringdataKey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                stringvalue = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                returnredis.SetEntryInHash(key, dataKey, value);
            }
        }
        /// <summary>
        /// 移除hash中的某值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        publicstatic bool Hash_Remove(stringkey, stringdataKey)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                returnredis.RemoveEntryFromHash(key, dataKey);
            }
        }
        /// <summary>
        /// 移除整个hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        publicstatic bool Hash_Remove(stringkey)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                returnredis.Remove(key);
            }
        }
        /// <summary>
        /// 从hash表获取数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        publicstatic T Hash_Get<T>(stringkey, stringdataKey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                stringvalue = redis.GetValueFromHash(key, dataKey);
                returnServiceStack.Text.JsonSerializer.DeserializeFromString<T>(value);
            }
        }
        /// <summary>
        /// 获取整个hash的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        publicstatic List<T> Hash_GetAll<T>(stringkey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                var list = redis.GetHashValues(key);
                if(list != null&& list.Count > 0)
                {
                    List<T> result = newList<T>();
                    foreach(var item inlist)
                    {
                        var value = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(value);
                    }
                    returnresult;
                }
                returnnull;
            }
        }
        /// <summary>
        /// 设置缓存过期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="datetime"></param>
        publicstatic void Hash_SetExpire(stringkey, DateTime datetime)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                redis.ExpireEntryAt(key, datetime);
            }
        }
        #endregion
 
        #region -- SortedSet --
        /// <summary>
        ///  添加数据到 SortedSet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="score"></param>
        publicstatic bool SortedSet_Add<T>(stringkey, T t, doublescore)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                stringvalue = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                returnredis.AddItemToSortedSet(key, value, score);
            }
        }
        /// <summary>
        /// 移除数据从SortedSet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        publicstatic bool SortedSet_Remove<T>(stringkey, T t)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                stringvalue = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                returnredis.RemoveItemFromSortedSet(key, value);
            }
        }
        /// <summary>
        /// 修剪SortedSet
        /// </summary>
        /// <param name="key"></param>
        /// <param name="size">保留的条数</param>
        /// <returns></returns>
        publicstatic int SortedSet_Trim(stringkey, intsize)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                returnredis.RemoveRangeFromSortedSet(key, size, 9999999);
            }
        }
        /// <summary>
        /// 获取SortedSet的长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        publicstatic int SortedSet_Count(stringkey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                returnredis.GetSortedSetCount(key);
            }
        }
 
        /// <summary>
        /// 获取SortedSet的分页数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        publicstatic List<T> SortedSet_GetList<T>(stringkey, intpageIndex, intpageSize)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                var list = redis.GetRangeFromSortedSet(key, (pageIndex - 1) * pageSize, pageIndex * pageSize - 1);
                if(list != null&& list.Count > 0)
                {
                    List<T> result = newList<T>();
                    foreach(var item inlist)
                    {
                        var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(data);
                    }
                    returnresult;
                }
            }
            returnnull;
        }
 
        /// <summary>
        /// 获取SortedSet的全部数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        publicstatic List<T> SortedSet_GetListALL<T>(stringkey)
        {
            using(IRedisClient redis = prcm.GetReadOnlyClient())
            {
                var list = redis.GetRangeFromSortedSet(key, 0, 9999999);
                if(list != null&& list.Count > 0)
                {
                    List<T> result = newList<T>();
                    foreach(var item inlist)
                    {
                        var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(data);
                    }
                    returnresult;
                }
            }
            returnnull;
        }
 
        /// <summary>
        /// 设置缓存过期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="datetime"></param>
        publicstatic void SortedSet_SetExpire(stringkey, DateTime datetime)
        {
            using(IRedisClient redis = prcm.GetClient())
            {
                redis.ExpireEntryAt(key, datetime);
            }
        }
        #endregion
    }
}

使用很简单,几行代码

1
2
3
4
5
//会往主服务里面写入
RedisBase.Hash_Set<string>("PooledRedisClientManager","one","123");
 
//从服务里面读取信息
RedisBase.Hash_Get<string>("PooledRedisClientManager","one");

连接池的初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
privatestatic string[] ReadWriteHosts = System.Configuration.ConfigurationSettings.AppSettings["readWriteHosts"].Split(newchar[] { ';'});
privatestatic string[] ReadOnlyHosts = System.Configuration.ConfigurationSettings.AppSettings["readOnlyHosts"].Split(newchar[] { ';'});
 
#region -- 连接信息 --
publicstatic PooledRedisClientManager prcm = CreateManager(ReadWriteHosts, ReadOnlyHosts);
 
privatestatic PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
{
    // 支持读写分离,均衡负载 
    returnnew PooledRedisClientManager(readWriteHosts, readOnlyHosts, newRedisClientManagerConfig
    {
        MaxWritePoolSize = 5, // “写”链接池链接数 
        MaxReadPoolSize = 5, // “读”链接池链接数 
        AutoStart = true,
    });
}

配置文件

总结

1.其实php,java等多种语言都能使用redis,在我接触的项目中见到使用redis做为消息队列和缓存组件,当然它的功能远不止于此。后面的文章将详细介绍redis的几个使用案例。

2.可以使用redis desktop manager管理工具查看服务器缓存中的数据

 1 赞  3 收藏  评论

相关文章

  • 分布式中使用 Redis 实现 Session 共享(下)
  • 分布式中使用 Redis 实现 Session 共享(中)
  • 如何用消息系统避免分布式事务?
  • .NET中使用Redis (二)
  • 关于Redis的常识
  • Web系统大规模并发:电商秒杀与抢购
  • 使用 Redis 实现分布式系统轻量级协调技术
  • Redis 3.0.0正式版发布,全新的分布式高可用数据库
  • Redis 的 5 个常见使用场景
  • 你真的很熟分布式和事务吗?

可能感兴趣的话题

  • Python用途广泛,但是大学却很少开这门课程... ·  24
  • 各位程序员,大家平时除了code,工作之余还有什么兴... ·  6
  • Android保存修改数据问题 ·  3
  • 一道ACM校赛题-大家来帮我看看啊
  • 学好Java反射,你就可以轻松搞定Java框架。
  • 百度之星大赛——一道简单而不简约的算法题
  • 局部变量和成员变量命名冲突问题 ·  6
  • 搞 IT 的怎么拿到年薪27万 ·  2
  • 大家有没有了解前端绘制拓扑图的开源库或插件? ·  2
  • Python有哪些库带给你最美的编程体验? ·  6
0 0
原创粉丝点击