缓存服务器 - Redis

缓存应用场景

1. 缓存热数据:  经常被查询, 但不经常被修改或者删除的数据

2. 计数器: (登陆密码错误记录, 浏览量等.) (最终要写入数据库, 可以每N条持久化一次)

3. 消息队列 (不过最好用专业的工具)

4. 排行榜,热点, 最新列表等 (可以采用 orderset, 一条条插入, 读取类似于 top10)

(待补充...)

 

注意:

1. 不要把缓存作为服务之间传递数据的媒介 (MQ更加合适)

2. 需要考虑缓存的雪崩效应, 即缓存失效后所有的压力都集中到数据库, 应对办法是可以设计缓存高可用或者水平切分

3. 最好不要多服务共用非只读缓存, 会引起数据覆盖问题

 

缺点:

1. 数据一致性, 实时性的影响

2. 不可靠性, 缓存很可能会带来数据消失的问题

 

memcache比较

参考链接: https://mp.weixin.qq.com/s/hOdwK2-7_S7_fi-KVu9_OQ

1. redis 支持多类型, mamcache 只支持 k/v

2. memcached 的内存利用率更高 (差距不大)

3. redis 使用单核 , memcached 使用多核, 所以平均在每一个核上redis在存储小数据时比memcached性能更高,而在100Ks=以上的时候memcached性能要高于redis

4. 内存管理机制的不同
在redis中,并不是所有的数据都一一直存储在内存中的,这是和memcached相比最大的一个区别
Redis只会缓存所有的key端的信息,如果redis发现内存的使用量超过某一个值,将触发swap的操作,redis根据相应的表达式计算出那些key对应value需要swap到磁盘,然后再将这些这些key对应的value持久化到磁盘中,同时再内存清除。同时由于redis将内存中的数据swap到磁盘的时候,提供服务的主线程和进行swap操作的子进程会共享这部分内存,所以如果更新需要swap的数据,redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改

5. redis 支持数据持久化(RBD和AOF), memcached 不支持

6. v 的大小, memcache 最大为1M, redis 为 512M

 

选型:

1. 有复杂数据类型的时候选 redis

2. 有持久化需求的时候选 redis (不建议缓存做持久化)

3. redis 天然支持高可用, memcache 需要二次开发

4. 纯KV, 数据量非常大, 并发量非常大的业务可以倾向于 memcache

 

简介:

Redis 是一种键值对形式的服务器

Redis包含服务端, 管理客户端, 连接器客户端

 

使用步骤: 

可以先下载 redis

目前可以下载以下几种版本的 redis

第一个 是未编译的 redis, 就是源代码开源, 可以自己拿来修改并生成

第二个 是已经编译好的, 可以拿来直接开启服务器

第三个 是客户端管理工具, 比如 redis Studio 和 redis Manager

第四个 是已经编译好的, 可以运用在各种项目环境下的 dll 文件

 

首先, 可以先下载一个服务端

目前版本是 3.1.6 据说 4 版本以后进行了商业收费

然后利用 管理员cmd 进入根目录

输入以下命令

redis-server  redis.windows.conf

就可以开启服务器

这仅仅是开启了服务器而已

如果要在代码中使用这个数据库 还需要 在 Nuget 上下载 ServiceStack.Redis.Complate

引用里面自带的4个dll

然后创建一个网上比较流行的封装好的类

public class RedisCacheHelper
    {
        private static readonly PooledRedisClientManager pool = null;
        private static readonly string[] redisHosts = null;
        public static int RedisMaxReadPool = int.Parse(ConfigurationManager.AppSettings["redis_max_read_pool"]);
        public static int RedisMaxWritePool = int.Parse(ConfigurationManager.AppSettings["redis_max_write_pool"]);
 
        static RedisCacheHelper()
        {
            var redisHostStr = ConfigurationManager.AppSettings["redis_server_session"];
 
            if (!string.IsNullOrEmpty(redisHostStr))
            {
                redisHosts = redisHostStr.Split(',');
 
                if (redisHosts.Length > 0)
                {
                    pool = new PooledRedisClientManager(redisHosts, redisHosts,
                        new RedisClientManagerConfig()
                        {
                            MaxWritePoolSize = RedisMaxWritePool,
                            MaxReadPoolSize = RedisMaxReadPool,
                            AutoStart = true
                        });
                }
            }
        }
        public static void Add<T>(string key, T value, DateTime expiry)
        {
            if (value == null)
            {
                return;
            }
 
            if (expiry <= DateTime.Now)
            {
                Remove(key);
 
                return;
            }
 
            try
            {
                if (pool != null)
                {
                    using (var r = pool.GetClient())
                    {
                        if (r != null)
                        {
                            r.SendTimeout = 1000;
                            r.Set(key, value, expiry - DateTime.Now);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "存储", key);
            }
 
        }
 
        public static void Add<T>(string key, T value, TimeSpan slidingExpiration)
        {
            if (value == null)
            {
                return;
            }
 
            if (slidingExpiration.TotalSeconds <= 0)
            {
                Remove(key);
 
                return;
            }
 
            try
            {
                if (pool != null)
                {
                    using (var r = pool.GetClient())
                    {
                        if (r != null)
                        {
                            r.SendTimeout = 1000;
                            r.Set(key, value, slidingExpiration);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "存储", key);
            }
 
        }
 
 
 
        public static T Get<T>(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                return default(T);
            }
 
            T obj = default(T);
 
            try
            {
                if (pool != null)
                {
                    using (var r = pool.GetClient())
                    {
                        if (r != null)
                        {
                            r.SendTimeout = 1000;
                            obj = r.Get<T>(key);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "获取", key);
            }
 
 
            return obj;
        }
 
        public static void Remove(string key)
        {
            try
            {
                if (pool != null)
                {
                    using (var r = pool.GetClient())
                    {
                        if (r != null)
                        {
                            r.SendTimeout = 1000;
                            r.Remove(key);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "删除", key);
            }
 
        }
 
        public static bool Exists(string key)
        {
            try
            {
                if (pool != null)
                {
                    using (var r = pool.GetClient())
                    {
                        if (r != null)
                        {
                            r.SendTimeout = 1000;
                            return r.ContainsKey(key);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("{0}:{1}发生异常!{2}", "cache", "是否存在", key);
            }
 
            return false;
        }
    }
View Code

在 web.config 的 appSetting 节点中 配置一下

<!-- redis Start   -->
<add key="SessionExpireMinutes" value="180" />
<add key="redis_server_session" value="127.0.0.1:6379" />
<add key="redis_max_read_pool" value="3" />
<add key="redis_max_write_pool" value="1" />
<!--redis end-->

最后可以调用这个类进行增加和删除缓存数据了

 

接下来, 如果一台服务器性能上还不够的话

可以设置主从分离的 redis 服务器

其重点是 在辅助的 redis 服务器的配置文件上

加上 slaveof 127.0.0.1 6379,  这个意思就是指向主 redis 服务器的 ip 和端口

然后在 C# 中调用的话, 跟之前区别不是很大

唯一需要注意的是 辅助 redis 服务器 似乎是只读的

所以可以在配置文件上下功夫, 令其读写分离

可以提高 服务器的性能

 

 

将 redis 注册为 服务

执行以下命令 ( 也可以是 redis.windows.server.conf )
redis-server.exe --service-install redis.windows.conf 
删除服务
redis-server --service-uninstall
开启服务
redis-server --service-start
停止服务
redis-server --service-stop


redis-server --service-install –service-name redisService1 –port 10001
redis-server --service-start –service-name redisService1
redis-server --service-install –service-name redisService2 –port 10002
redis-server --service-start –service-name redisService2
redis-server --service-install –service-name redisService3 –port 10003
redis-server --service-start –service-name redisService3

 

 

 

连接器:

Jedis

Lettuce

posted @ 2017-08-05 16:57  `Laimic  阅读(253)  评论(0)    收藏  举报