ServiceStack.Redis Encapsulation and Simple Cracking

Keywords: C# Redis Database github

1.ServiceStack.Redis Packaging

The encapsulated RedisHandle operation class is named RedisHandle, with the following code blocks (showing only part of the code). Its features are as follows:

1) Manage connections using connection pools, as shown in the PooledClientManager property in the code. If the connection pool is not used, but the code directly RedisClient client = new RedisClient ("localhost", "6379", "password"); to get a connection instance operation, then when Redis operation is frequent, the cost is very high and it is not feasible.

2) Redis server that supports read-write separation (if you only use one Redis server, then read-write server can connect strings as well).

3) When operating Redis, read and write Redis connection instances are automatically switched. See the GetRedisClient function in the code. All write operations take "write connection instance" PooledClient Manager. GetClient (), and all read operations take "read connection instance" PooledClient Manager. GetReadOnlyClient ().

Note: If you read and write are two Edits servers that make master-slave replication, consider whether master-slave replication is delayed, whether there are some read operations that require real-time data, and if so, use write connection instances when GetXX reads data. At this point, you can rewrite the GetXX function to add bool? isReadOnly = null at the end of the function parameter with default values, that is, to support external calls to specify which connection instance operation to use. In this case, the system usually regards Redis as a NoSql database; more often, our system regards Redis as a cache, and does not need master-slave replication. Read-write connection instances point to the same Redis server. When the system is large, caching clusters (such as consistency hash caching) may be used.

4) Subsequently, if Redis needs to do consistency hashing and other clusters, it can instantiate multiple RedisHandle instances, and then write an algorithm to extract the corresponding RedisHandle instances.  

  1 namespace NetDh.RedisUtility
  2 {
  3     /*
  4      * A RedisHandle instance corresponds to a Redis server or a group of master-slave replication Redis servers.
  5      * If Redis needs to do consistency hashing and other clustering, it is necessary to write its own algorithm to take the corresponding RedisHandle instance.
  6      */
  7 
  8     /// <summary>
  9     /// Redis Operation class
 10     /// </summary>
 11     public class RedisHandle
 12     {
 13         /// <summary>
 14         /// Redis Connection pool management example
 15         /// </summary>
 16         public PooledRedisClientManager PooledClientManager;
 17 
 18         /// <summary>
 19         /// Constructor
 20         /// </summary>
 21         /// <param name="poolManager"></param>
 22         public RedisHandle()
 23         {
 24             #region This code creates the Connection Pool Example, and configures information directly using static classes RedisClientConfig1 Hosting, you can also choose to load with configuration files
 25             var config = new RedisClientManagerConfig
 26             {
 27                 AutoStart = true,
 28                 MaxWritePoolSize = RedisClientConfig1.MaxWritePoolSize,
 29                 MaxReadPoolSize = RedisClientConfig1.MaxReadPoolSize,
 30                 DefaultDb = RedisClientConfig1.DefaultDb,
 31             };
 32             //If you only use one Redis On the server side, you can specify the same connection string when configuring read and write.
 33             PooledClientManager = new PooledRedisClientManager(RedisClientConfig1.ReadWriteServers
 34                 , RedisClientConfig1.ReadOnlyServers, config)
 35             {
 36                 ConnectTimeout = RedisClientConfig1.ConnectTimeout,
 37                 SocketSendTimeout = RedisClientConfig1.SendTimeout,
 38                 SocketReceiveTimeout = RedisClientConfig1.ReceiveTimeout,
 39                 IdleTimeOutSecs = RedisClientConfig1.IdleTimeOutSecs,
 40                 PoolTimeout = RedisClientConfig1.PoolTimeout
 41             };
 42             #endregion
 43         }
 44         /// <summary>
 45         /// Constructor
 46         /// </summary>
 47         /// <param name="poolManager"></param>
 48         public RedisHandle(PooledRedisClientManager poolManager)
 49         {
 50             //It can also be imported externally into self-created ones. PooledRedisClientManager object
 51             PooledClientManager = poolManager;
 52         }
 53         /// <summary>
 54         /// Obtain Redis Client connection instance, connection pool management.
 55         /// </summary>
 56         /// <param name="isReadOnly">Read-only connection. Get The operation is generally reading. Set Operations are usually written</param>
 57         /// <param name="db">One Redis The server defaults to 16 databases, and the default is to use the 0 database. If you need to switch the database, pass in db value(0~15)</param>
 58         /// <returns></returns>
 59         public RedisClient GetRedisClient(bool isReadOnly = false, int db = 0)
 60         {
 61             RedisClient result;
 62             if (!isReadOnly)
 63             {
 64                 //RedisClientManager.GetCacheClient()A new instance will be returned, and only a small number of methods will be provided to help you decide whether to write or read an instance.
 65                 result = PooledClientManager.GetClient() as RedisClient;
 66             }
 67             else
 68             {
 69                 //If you read and write two master-slave copies Redis On the server side, consider whether master-slave replication is delayed. Whether some read operations are real-time or not needs to be retrieved in a write instance.
 70                 result = PooledClientManager.GetReadOnlyClient() as RedisClient;
 71             }              
 72 
 73             if (db > 0)
 74                 result.ChangeDb(db);
 75             return result;
 76         }
 77 
 78         #region Storage single value key-value,among value yes string,When used, if value yes int,For example int Turn into string storage
 79         public void SetValue(string key, string value, int expirySeconds = -1)
 80         {
 81             using (RedisClient redisClient = GetRedisClient())
 82             {
 83                 //redisClient.SetEntry(key, value, expireIn);
 84                 if (expirySeconds == -1)
 85                 {
 86                     redisClient.SetValue(key, value);
 87                 }
 88                 else
 89                 {
 90                     redisClient.SetValue(key, value, new TimeSpan(0, 0, 0, expirySeconds));
 91                 }
 92             }
 93         }
 94 
 95         public string GetValue(string key)
 96         {
 97             using (RedisClient redisClient = GetRedisClient(true))
 98             {
 99                 var val = redisClient.GetValue(key);
100 
101                 return val;
102             }
103         }
104 
105         public bool Remove(string key)
106         {
107         ...

5) In the GetRedisClient function, an int db parameter is also given, when used: if (db > 0) result.ChangeDb(db); ChangeDb is to switch the Redis database (Redis defaults to 16 databases, see "databases 16" in the redis.conf configuration file in the redis-server.exe directory). We usually default to use the 0th database. If we need to switch the database, we pass in the DB value (0-15). I don't usually use the need to switch databases here. If your system is used frequently, you can add "int db=0" parameters with default values in GetXX and SetXX functions.

To illustrate that a Redis server has multiple databases and switching between databases, let's take a small example. As shown below, I stored the key value "test2:1" in Redis's 0th database. When I cut to ChangeDb(1) of the 1st database, GetValue("test2") returned null, and when I cut back to the 0th database, I got the value of 1.

Now login Redis with the command to demonstrate this process again, as follows:

6) The RedisHandle operation class contains more operations than Memcache, and it is practical. If your system access cache involves more complex logic, Redis is recommended. Memcache-enabled Redis can be used.

For the complete source code, please refer to: https://gitee.com/donghan/NetDh-Framework/tree/master/Data/NetDh.RedisUtility

This tool class has been incorporated into my NetDh framework project, the NetDh framework code cloud address: https://gitee.com/donghan/NetDh-Framework

 

2. Service Stack. Redis Cracking

My encapsulation here is ServiceStack. Redis's latest version 5.7.0, which has been commercialized since version 4.0 and is limited to 6,000 Redis visits per hour. ServiceStack.Redis and StackExchange.Reids are compared on the Internet. The result is that the former has better performance. No matter whether it is true or false, I am ServiceStack.Redis 3.x. I began to use it. As always, I continue to use it.

Steps:

1) Restriction 6000 times is in ServiceStack.Text.dll, and in two places, use ILSpy to open ServiceStack.Text.dll, enter "RedisRequest PerHour" in the search bar, you can see the restriction of RedisRequest PerHour = 6000, as shown below (Step 1 you can not do it, just look at it):

Search "Assert Valid Usage" again and find 6,000 restrictions in another place, as follows:

2) Download a hexadecimal editor. I'm looking for the wxMEdit tool (download page: http://wxmedit.github.io/downloads.html).

3) First, backup ServiceStack.Text.dll and open ServiceStack.Text.dll with hexadecimal editor.

Analysis: 6000 is converted into byte form of 7017 000 (although the hexadecimal system of 6000 is 00001770), the maximum value of int 2147 483647 is converted into byte form of FF FF 7F, so as long as 7017 00 is replaced by FF FF 7F.

In the following figure, before replacing, click "Find Next" to find the whole situation in two places, then make sure the value to be modified, then click "Replace" twice, ctrl+s saves the file, and dll modification is completed.

4) Look at these two values with ILSpy and they have been modified, as shown in the following figure (step 4, you can't do it, just look at it):

5) To overwrite the original DLL with the modified dll, it is better to remove the original reference in the IDE and add the reference again in case the old DLL is executed by the cache. Write the following code tests:

The limit of 6000 will be reported before overwriting dll, and the output ok will be normal after overwriting:

Perfect, compliment!

Posted by mw-dnb on Mon, 07 Oct 2019 22:08:34 -0700