<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Worlds second best Harald]]></title><description><![CDATA[Notes to self on software development ]]></description><link>https://ulriksenblog.azurewebsites.net/</link><image><url>https://ulriksenblog.azurewebsites.net/favicon.png</url><title>Worlds second best Harald</title><link>https://ulriksenblog.azurewebsites.net/</link></image><generator>Ghost 3.42</generator><lastBuildDate>Mon, 06 Apr 2026 22:43:11 GMT</lastBuildDate><atom:link href="https://ulriksenblog.azurewebsites.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[State versioning in Orleans]]></title><description><![CDATA[An example on handling state persistence in stateful systems with continuous delivery.]]></description><link>https://ulriksenblog.azurewebsites.net/state-versioning-in-orleans/</link><guid isPermaLink="false">5e35d0f7e2e748000182ab12</guid><category><![CDATA[Orleans]]></category><category><![CDATA[F#]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 06 Feb 2020 07:48:00 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/fredy-jacob-t0SlmanfFcg-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/fredy-jacob-t0SlmanfFcg-unsplash.jpg" alt="State versioning in Orleans"><p>The documentation on <a href="https://dotnet.github.io/orleans/Documentation/deployment/grain_versioning/grain_versioning.html">Grain versioning</a> in Microsoft Orleans starts off with this </p><p>"👉WARNING: This page describes how to use grain interface versioning. The versioning of Grain state is out of scope." </p><p>With a stateful system handling multiple state versions is a must if we want to deploy new versions without taking the whole system offline. Working with F# we have some powertools in our belt, and for dealing with multiple versions we decided to try out <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/discriminated-unions">Discriminated Unions</a>, and they worked our great. One can of course apply the same technique in C# with a bit more checks.</p><h3 id="tl-dr-">tl;dr;</h3><p>The short version (phun intented) is: <br>Discriminated union with one entry per version and a module which is capable of upgrading old versions as they are loaded from storage. Writing state always write the latest version. </p><h3 id="example">Example</h3><p>Let's say we have a state where we wish to go from a single image to an array if images, just changing the field type would not work. Lets call this ImageState</p><p> The goal is for our grain implementation not to worry too much about versions, to do this we separate the in memory representation, state, in our case called <code>ImageState</code> from the DTO representation called <code>ImageStateDto</code>. </p><p>The in memory representation which the grain works with <code>ImageState</code> has a simple list of images uri's</p><pre><code class="language-F#">type ImageState = { images: Uri list }</code></pre><p>Our stored representation of this can be both the new version and old version</p><pre><code class="language-F#">type ImageStateDtoV1 = { image: Uri option }
type ImageStateDtoV2 = { images: Uri list}
type ImageVersionedStateDto = 
    | V1 of ImageStateDtoV1
    | V2 of ImageStateDtoV2</code></pre><!--kg-card-begin: html--><div style="background-color: #CD5C5C; padding: 5px"><strong>Update:</strong><br> Be sure to start with at least two cases and test with your binary serializer. With Orleans default binary serializer, single case discriminated unions will yield different format, hence fail deserialization</div><!--kg-card-end: html--><p>Since Orlans must be able to create new, empty versions of the state object we'll wrap this with a class and also add a module which can convert from Dto to State and from State to Dto. </p><pre><code class="language-F#">type ImageStateDto(state: ImageVersionedStateDto) =
    member val State = state with get, set
    new () = ImageStateDto({ images = []} |&gt; V2)

module ImageStateDto =
    let fromDto (dto:ImageStateDto)  =
        match dto.State with
        | V1 dto -&gt; 
            match dto.image with
            | Some i -&gt; { ImageState.images = [i]}
            | None _ -&gt; { ImageState.images = []}
        | V2 dto -&gt; 
            { ImageState.images = dto.images}
    let toDto (state:ImageState) : ImageStateDto =
        { ImageStateDtoV2.images = state.images} |&gt; V2 |&gt; ImageStateDto</code></pre><p>The <code>ImageStateDto</code> is the class which will be injected into the grain constructor as <code>IPersistentState&lt;ImageStateDto&gt;</code> . Inside the grain we wrap the IPersistentState to read the state using the <code>fromDto</code> method. Instead of calling <code>WriteStateAsync</code> directly we have our own internal method using <code>ImageStateDto.toDto</code> before calling WriteStateAsync.  A sample grain may look like this</p><pre><code class="language-F#">type ProfileImage =
    inherit Grain
    
    val private persistence : IPersistentState&lt;ImageStateDto&gt; 

    new (persistence) = {
        persistence = persistence
    }
    member this.State 
        with get() = this.persistence.State |&gt; ImageStateDto.fromDto
    
    member private this.WriteStateAsync(state)  =
        this.persistence.State &lt;- state |&gt; ImageStateDto.toDto
        this.persistence.WriteStateAsync()</code></pre><p>It may seem a bit tedious, but we've found this to work very well for our needs. </p><p><br> </p>]]></content:encoded></item><item><title><![CDATA[Deploying Orleans to Kubernetes]]></title><description><![CDATA[An overview of how we do continuous deliver of a stateful system based on the actor model.]]></description><link>https://ulriksenblog.azurewebsites.net/deploying-orleans-to-kubernetes/</link><guid isPermaLink="false">5e2c48192807240001af2d74</guid><category><![CDATA[Orleans]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Azure]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Sat, 01 Feb 2020 19:12:49 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/01/nola.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/nola.jpg" alt="Deploying Orleans to Kubernetes"><p>We've been running Microsoft Orleans in Kubernetes for nearly 2 years, and for the last half year or so we've had full continuous delivery whenever we commit to master branch in GitHub. <br><br>On GitHub there is an <a href="https://github.com/dotnet/orleans/issues/6178#">issue</a> to gather details for Orleans production usage, and recently k8s popped up in the chat for the <a href="https://www.youtube.com/watch?v=an87dzgAMR8">latest virtual meetup</a>. A safe and sound deployment regime is the basis for running Orleans in production, so documenting how we do this will be my first contribution. How we do our deploys will touch base on multiple subjects, such as <a href="https://blog.ulriksen.net/state-versioning-in-orleans/">state versioning</a>, testing, feature toggles and metrics. In this blog post I will give an introduction to our application , continuous delivery pipeline and how we deploy to Azure Kubernetes Service (AKS) without downtime. </p><h3 id="deployables">Deployables</h3><p>Our application consists of 3 deployables, an API running together with Orleans (the direct client is quite a bit faster), a service processing write messages from the API and another service processing messages from our internal systems. From deployment perspective and important detail is the use of Azure Service Bus</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://imgr.whimsical.com/TRaEpE7xZxzR9RBXS2WE3h/png?objects=BoWzL3L87HDDfrQ8wKP9yj%2CYLME9y1VAzBeRaTHpPtwFR%2C3kckr8zu1EwFUG5Xg78F51%2CNDPX976h7BFqV5W9UeTZfv%2CVqHeJRbAgdoiBkKEVPuo6c%2CRF85qNVxpNPq5L98kMDNcM%2CTFDUvtA4dKp1oS5RoZEDs2%2CN79vFBKn9ck7XETsFGZLh1%2CKU8caTE7vZeDvYKeHTifJA%2CSnuYPgf1SNwpzcq2RBHzuQ%2CBQfRiKEy7WmR4JEZfaUYeV&amp;scale=2&amp;stag=5149" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>Deployables</figcaption></figure><p>Users perform both read and write operations using the API, all writes goes through Azure Service Bus before being picked up and persisted (we're considering writing directly by default and only use Service Bus in case of write failuers).</p><!--kg-card-begin: html--><div style="background-color: #FFFFE0; padding: 5px"><strong>Update:</strong><br> We do not use the Orleans.Clustering.Kubernetes provider, we use AzureStorageClustering. The clustering provider is just for reading and writing cluster information. It is not related to the actual hosting model.z</div><!--kg-card-end: html--><h3 id="deployment-pipeline">Deployment pipeline</h3><p>The deploy pipeline is rather straing forward, and fully automated from the point a pull request is merged to master. The deployment will go through two environemnts before our production environment. The first environment we deploy to, stage, has data we can modify to provoke failures. The next environment is our pre-production where data is replicated from our production environment at regular intervals. Finally we have our production environment. We currently run in one data center only as the service provides added value, not primary functionality. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://imgr.whimsical.com/TRaEpE7xZxzR9RBXS2WE3h/png?objects=CTBHMf3xZ5WRndR9RntcfQ%2C6KzSb6f9Ha3gidhjWN4svs%2CXqXjsUF5VhgiyyJmNAins8%2CL5poEBcdJEifpaCcsebwGA%2CKMESvgKuKcRUk4Vc28rYZt%2CNGBC5DPQUJzeCXxsSfj6Lc%2CALAeYZbLYhHKQAUaRt2RHi%2CWnirrpuRS1kDjqfcvBGWCc%2CLD5qg9e5F1SfKZdYTycSfG%2CLmEmaUHREhH9jmx9gqsQBe%2C9d7xKfZskyNHBnFE6n2wpA%2C8K49H9PcxWdSEoyoTzQgDZ&amp;scale=2&amp;stag=5084" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>CI/CD Pipeline with Github, TeamCity, Octopus Deploy, Azure Container Service and Azure Kubernetes Service</figcaption></figure><ol><li>When something is comitted to master, TC will trigger a build using our docker build container </li><li>TC will run unit and integration tests</li><li>TC will upload the 3 images to Azure Container Registry</li><li>TC will upload a support package to octopus which contains our deploymen script, config file templates ++ </li><li>Octopus will create deployment started annotations in Application Insights</li><li>Octopus deploy will execute the deployment script against Kubernetes </li><li>After deployment Octopus wil create annotations in Application Insights and notify on slack</li></ol><h3 id="the-deployment">The deployment </h3><p>Orleans supports <a href="https://www.martinfowler.com/bliki/BlueGreenDeployment.html">blue green deployments</a>, with multiple versions of the same grain type, given the interfaces is versioned as well as versioning state if need. See the Orleans documentation <a href="https://dotnet.github.io/orleans/Documentation/grains/grain_versioning/grain_versioning.html">here</a>. I've written about our state versioning technique in a separate <a href="https://blog.ulriksen.net/state-versioning-in-orleans/ ">blog post</a>.</p><p>When deploying Orleans to Kubernetes I would either go for a single <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/">StatefulSet</a> or multiple deployments. We chose the latter as we also version our Service Bus topics. Note that both methods will require that </p><p>When we start rolling our a deployment we place an annotation in Applications Insights, making it easy to correlate any anomalies with the deployments. The deploymen also contains a link to our internal release note which has a list of all pull requests since the previous version. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/image-1.png" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>Annotations in application insights, blue is start of deployment and green is posted on success. Red if it fails</figcaption></figure><p></p><p>Before the deployment we have a service and the apps in V1, and an ingress which we'll reuse.  </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/image.png" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>Before the deployment</figcaption></figure><p>During deloy we add the new version and a new temporary ingress for smoke tests. The tests verify that our api respons as expected. Note the dashed line in the diagram below, once the new silos are in the cluster they will start recieving traffic. Also, we have some stateless grains, which read their data from a stateful grain, chances are our tests will hit stateless grains in the new slio which will load its data from v1 grains, not v2. If we were to verify this as well we would need to shutdown both versions, and fire up v2 alone. This is not something we can do in production, but it is possible in other environments. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://imgr.whimsical.com/TRaEpE7xZxzR9RBXS2WE3h/png?objects=QGEEGztjvSJDiMX7nU6k4%2C5EYv4Umh1GTHrPwBKEsRbc%2CJRhn6dZpsW6izJZUJGGpuq%2CN5QBY3UMCnpf1xRJC7KH6a%2CPiECsAdpgH8GNrNAWBrYQw%2C6mEgXuM5ecNL7zi7ZiksQD%2CYQM9tJbVXeLSmL2gm8Lcaa%2CCGEdiAQ4WdaUhd3SEeNNf1%2CCQkpp4kqCUhzy5U2vyB5j7%2C3DnjoxeVwY4t8ecE3i4JKs%2CHqm35jQVMR8wrvUbA8g4xE%2CDPmnMei2nwE9CGQMdH21ng%2CBZhPxd58DDMAdTABUPfPkA%2CPiZoD2qzaR9jVTL5VM5igR%2C4Cppf44RACJNGz7t1qGnKx%2CBgpBrtDUZ4FZr3G9SnQUUG%2CzJdCygTc5E9bEa7jsP5wz%2CXx4NqwrX3sj6jMW3k1cqrn%2C3EHkuCbP2LYhmYMTH7f55B%2CLb4oWFpGjGD2GbJjdKRfm9&amp;scale=2&amp;stag=5324" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>During deploy</figcaption></figure><p>When we're satisfied with our tests we'll delete the smoke test ingress, switch the old ingress from v1 to v2. We'll then start shutting down the old silos by reducing the replica count 1 by 1, waiting between each one until it is unloaded before shutting down the next one.</p><p>We finish off the deployment by placing a deployment completed marker in Application insights</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://imgr.whimsical.com/TRaEpE7xZxzR9RBXS2WE3h/png?objects=QGEEGztjvSJDiMX7nU6k4%2C5EYv4Umh1GTHrPwBKEsRbc%2CJRhn6dZpsW6izJZUJGGpuq%2C6mEgXuM5ecNL7zi7ZiksQD%2CXbmwLDHcUGdC44uhkmLpKa%2CYQM9tJbVXeLSmL2gm8Lcaa%2CCQkpp4kqCUhzy5U2vyB5j7%2CBZhPxd58DDMAdTABUPfPkA%2CPiZoD2qzaR9jVTL5VM5igR%2C4Cppf44RACJNGz7t1qGnKx&amp;scale=2&amp;stag=5328" class="kg-image" alt="Deploying Orleans to Kubernetes"><figcaption>After deploy</figcaption></figure><h3 id="failures">Failures</h3><p>On the off chance our smoke tests fails we start taking down the new silos one by one. This goes without any serious problems in production as we have already rolled out through 2 other environments (we've had to wipe staging a few times)</p><h3 id="do-you-ever-have-to-do-a-full-shutdown-during-deploy">Do you ever have to do a full shutdown during deploy?</h3><p>Yes, we have one grain where we did not bother versioning the state. It means that whenever we change this grain we have to stop all silos and spin up the new ones, resulting in downtime. This is automated in our deploy script, and is based on a label on the pull requests in github. We should propably start versioning that state as well to get out of it. The other case we have seen is when we have incompatibilities in the request context, causing everything to blow up.</p><h3 id="what-could-be-better">What could be better? </h3><p>Both the warmup and shutdown of silos perhaps. It would be nice to have a silo join the cluster, and only have specific grains/calls to it. Just to keep it free from production traffic on it before our smoke tests are done. Same goes for shutdown, when our tests are fine I would very much like the existing silos to "empty" themself of grains before shutting down and not recieving any new activations. It probably works like this already, but we do see a handful of exceptions during shutdown and it would be nice to be able to do shutdowns without any exception entries in our logs. I have thought about writing a custom placement director to do this, but so far it is just a thought.</p>]]></content:encoded></item><item><title><![CDATA[Understanding grain references and UniqueKey for Orleans CosmosDB provider]]></title><description><![CDATA[An explanation of the Grain Reference in Microsoft Orleans]]></description><link>https://ulriksenblog.azurewebsites.net/orleans-grain-references/</link><guid isPermaLink="false">5e2472562807240001af2c97</guid><category><![CDATA[Orleans]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 21 Feb 2019 12:10:00 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/martin-adams-_OZCl4XcpRw-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/martin-adams-_OZCl4XcpRw-unsplash.jpg" alt="Understanding grain references and UniqueKey for Orleans CosmosDB provider"><p>As a part of enabling custom partition keys on the cosmosDb provider I wanted to get a better understanding of the id used in the documents stored in CosmosDB, so I decided I could just as well do a write up of it as a part of the learning experience.</p>
<p>Here's an example of an id</p>
<pre><code>b780de47-a7d2-44c5-8a8f-7eea29e9561f__GrainReference=4fb7889c000475dcf1a50290320ead970600000000000000+13f58135-de2b-4ec7-8f5b-ae609c6d8cbb
</code></pre>
<p>After a bit of digging it is not as bad as it looks, the pattern is <code>{ClusterServiceId}__{GrainReference.KeyString}</code>. The GrainReference.KeyString has four different formats</p>
<ul>
<li>Observer reference = <code>GrainReference={GrainId} ObserverId={ObserverId}</code></li>
<li>System target = <code>GrainReference={GrainId} SystemTarget={Silo Address}</code></li>
<li>Generic argument = <code>GrainReference={GrainId} GenericArguments={genericArguments}</code></li>
<li>Grain reference = <code>GrainReference={GrainId}</code></li>
</ul>
<p>In our case we're looking at grain references. The GrainId is a string created by calling  <code>GrainId.GrainToParsableString</code> which in turn calls on <code>UniqueKey.ToHexString()</code></p>
<p>So this seems straight forward, right. Well just almost. The id <code>4fb7889c000475dcf1a50290320ead970600000000000000+13f58135-de2b-4ec7-8f5b-ae609c6d8cbb</code> is from a grain created calling <code>GetGrain(new Guid(&quot;000475dc-889c-4fb7-97ad-0e329002a5f1&quot;), &quot;13f58135-de2b-4ec7-8f5b-ae609c6d8cbb&quot;);</code></p>
<p>Last part first, when using composite grain keys the last part is preserved as is, after a + sign. The first part is a bit more of a puzzle. To get to this we have to look at the implementation in <a href="https://github.com/dotnet/orleans/blob/master/src/Orleans.Core.Abstractions/IDs/UniqueKey.cs">UniqueKey</a>. Provided we're after a grain reference the call chain from GrainReference is <code>GrainReference.ToKeyString -&gt; GrainId.ToParsableString -&gt; UniqueKey.ToHexString</code>. The string before the <code>+</code> sign is built with the following format <code>s.AppendFormat(&quot;{0:x16}{1:x16}{2:x16}&quot;, N0, N1, TypeCodeData);</code> (x16 formats to hexadecimal string of 16 digits.).</p>
<p>Starting from the end again, typecode is used to identify the Grain implementation with any generic parameters (it can be overridden by <a href="https://github.com/dotnet/orleans/blob/b279a53197a0de2926eb9fae312bc9e66cd117e1/src/Orleans.Core.Abstractions/CodeGeneration/CodeGenGrainAttributes.cs#L10">TypeCodeOverrideAttribute</a>). The typecode is a SHA256 hash based on the <a href="https://github.com/dotnet/orleans/blob/b279a53197a0de2926eb9fae312bc9e66cd117e1/src/Orleans.Core/CodeGeneration/GrainInterfaceUtils.cs#L429">full name of the class with generic arguments</a>.</p>
<p>All we're left with is the first two longs, which for our case is easy enough. When the UniqueKey is initialized the Guid it is converted to 2 int64's</p>
<pre><code>var n0 = BitConverter.ToUInt64(guidBytes, 0);
var n1 = BitConverter.ToUInt64(guidBytes, 8);
</code></pre>
<p>And that's it.</p>
<p>There's some discussions on this when searching Gitter, and there's some proposals to change how this works <a href="https://github.com/dotnet/orleans/issues/1123">https://github.com/dotnet/orleans/issues/1123</a> and <a href="https://github.com/dotnet/orleans/issues/3049">https://github.com/dotnet/orleans/issues/3049</a> and <a href="https://github.com/dotnet/orleans/issues/1121#issuecomment-303951424">https://github.com/dotnet/orleans/issues/1121#issuecomment-303951424</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Easy scaling with Cosmos DB for large loads]]></title><description><![CDATA[Learn how to scale Cosmos DB in a easy and transparent way using the decorator pattern.]]></description><link>https://ulriksenblog.azurewebsites.net/easy-scaling-documentdb-for-large-loads/</link><guid isPermaLink="false">5e2472562807240001af2c95</guid><category><![CDATA[scalability]]></category><category><![CDATA[DocumentDB]]></category><category><![CDATA[Cosmos DB]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Tue, 04 Jul 2017 18:41:15 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/akshay-nanavati-8FevUlxdZC0-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/akshay-nanavati-8FevUlxdZC0-unsplash.jpg" alt="Easy scaling with Cosmos DB for large loads"><p>Working with a customer we need to load a batch of 40-50K documents to Cosmos DB. We could let this pass, but it will result in quite a few HTTP 429 RequestRateTooLarge responses. The operation will be retried, but it will also hurt other clients accessing the same data. Potentially causing a cascade of 429's and possibly degraded performance for other clients, with real humans waiting.</p>
<p>To prevent this we can scale up to the required request units. This is easily done through code</p>
<pre><code>offer = _documentClient.CreateOfferQuery().Where(o =&gt; o.ResourceLink == collection.SelfLink).AsEnumerable().Single();

await _documentClient.ReplaceOfferAsync(new OfferV2(offer,   HighThroughputRequestUnits));
</code></pre>
<p>After processing our batch we can scale down again using the same technique.</p>
<p>Provided we have a IBatchJob interface, we can then use the <a href="https://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a> to wrap our batch job with a HighThroughputBatchJobDecorator, which will scale up Cosmos DB, execute the original BatchJob and scale it down again.</p>
<pre><code>public class HighThroughputBatchJobDecorator : IBatchJob
{
	private const int HighThroughputRequestUnits = 10000;

	private IBatchJob _batchJob;
	private IDocumentClient _documentClient;
    private IDocumentDBConfig _config;

    public HighThroughputBatchJobDecorator(IBatchJob batchJob, IDocumentClient documentClient, IDocumentDBConfig config)
    {
        _batchJob = batchJob;
        _documentClient = documentClient;
        _config = config;
    }
    public async Task RunAsync(Uri feedUri, XElement feedXml)
    {
        Offer offer = null;

        try
        {
            DocumentCollection collection = _documentClient.CreateDocumentCollectionQuery(UriFactory.CreateDatabaseUri(_config.DatabaseName))
            .Where(c =&gt; c.Id == _config.CollectionId).ToArray().Single();

            offer = _documentClient.CreateOfferQuery().Where(o =&gt; o.ResourceLink == collection.SelfLink).AsEnumerable().Single();
            await _documentClient.ReplaceOfferAsync(new OfferV2(offer, HighThroughputRequestUnits));

            Trace.WriteLine(&quot;Running with high througput&quot;);
    
            await _batchJob.RunAsync(feedUri, feedXml);
        }
        finally    
        {
            if (offer != null)
            {
            	// Scale down
                await _documentClient.ReplaceOfferAsync(offer);

                Trace.WriteLine(&quot;Collection scaled down from high throughput&quot;);
            }
        }
    }
}
</code></pre>
<p>Pretty neat ;)</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Default indexing in Cosmos DB]]></title><description><![CDATA[Creating Cosmos DB collections in .NET SDK yields different indexing settings than the portal. This post shows you how to create one with default indexing]]></description><link>https://ulriksenblog.azurewebsites.net/default-indexing-in-cosmos-db/</link><guid isPermaLink="false">5e2472562807240001af2c94</guid><category><![CDATA[DocumentDB]]></category><category><![CDATA[Cosmos DB]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 22 Jun 2017 10:53:48 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/kolar-io-lRoX0shwjUQ-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/kolar-io-lRoX0shwjUQ-unsplash.jpg" alt="Default indexing in Cosmos DB"><p>I recently needed some paging functionality in Cosmos DB, since skip and take is not directly supported we're using a cursor based paging based on a date time. While testing my repository I suddenly did not get the results I expected. After a little bit of trial and error with the Query Explorer in the portal I noticed somethign important</p>
<blockquote>
<p>Creating collections with the SDK will not use the same index configuration as collections created through the portal.</p>
</blockquote>
<p>I had added code to create the collection automatically, and after testing this my collection used the &quot;old&quot; index settings.</p>
<p>I have blogged about this earlier, <a href="http://blog.ulriksen.net/indexing-changes-in-documentdb/">http://blog.ulriksen.net/indexing-changes-in-documentdb/</a> but totally forgotten about it since then.</p>
<p>So, how do you create a new collection with default indexing using the .NET SDK?</p>
<script src="https://gist.github.com/Ulriksen/d04575733fea468226d1e3542c67b87f.js"></script>
<p>I did a shout out to the Azure Cosmos DB team, and they confirmed this will change</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">And yes, the plan is to change the SDK defaults so that they&#39;re the same.</p>&mdash; Azure Cosmos DB (@AzureCosmosDB) <a href="https://twitter.com/AzureCosmosDB/status/877595399103553537">June 21, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Running group select]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>We're currently working on creating a somewhat large XML file where we need to read records from our database, perform some calculations on a small subset of the records based on a key, and then write everything to a blob.</p>
<blockquote>
<p>Services such as Azure functions, which are priced by memory</p></blockquote>]]></description><link>https://ulriksenblog.azurewebsites.net/running-group-select/</link><guid isPermaLink="false">5e2472562807240001af2c93</guid><category><![CDATA[Linq]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 08 Sep 2016 18:48:00 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/neonbrand-vlopP4TuHHk-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/neonbrand-vlopP4TuHHk-unsplash.jpg" alt="Running group select"><p>We're currently working on creating a somewhat large XML file where we need to read records from our database, perform some calculations on a small subset of the records based on a key, and then write everything to a blob.</p>
<blockquote>
<p>Services such as Azure functions, which are priced by memory consumption, makes .ToList() more than a triviality</p>
</blockquote>
<p>As it is now we have excluded a lot of content and we can safely read the whole set into memory, but we know that our dataset will grow, and I someone decides to include our archives, we will run out of memory.</p>
<h2 id="enumeratorstotherescue">Enumerators to the rescue</h2>
<p>As we only need a small subset of the data in memory at the same time we can work with an enumerator and then read in batches, perform our operations and then write the data to disk. Fairly easy, however we needed to do this more than one place and I figured I could just as well write it as a general Linq-ish function.</p>
<blockquote>
<p>NOTE: This does only make sense when you do not want to load the whole dataset into memory and the data is sorted by the key selector</p>
</blockquote>
<pre><code>IEnumerable<tresult> RunningGroupSelect<tsource, tkey, tresult>(this IEnumerable<tsource> source, Func<tsource, tkey> keySelector, Func<tkey, ienumerable<tsource>, IEnumerable<tresult>> resultSelector)
</tresult></tkey,></tsource,></tsource></tsource,></tresult></code></pre>
<p>The method signature takes a regular TKey. When enumerating over the source the result will be buffered until the result of the KeySelector changes. When the KeySelector changes, the key and the collected buffer will be passed to the result selector function. The calling code will then enumerate over the result without noticing anything to the buffering.</p>
<p>A use case is calculating availability for a season based on the rights for each episode.</p>
<pre>
<code>
 public static IEnumerable<tresult> RunningGroupSelect<tsource, tkey, tresult>(this IEnumerable<tsource> source, Func<tsource, tkey> keySelector, Func<tkey, ienumerable<tsource>, IEnumerable<tresult>> resultSelector)
        {
            return new GroupedResultIterator<tsource, tkey, tresult>(source.GetEnumerator(), keySelector, resultSelector);
        }
    }
    
    internal sealed class GroupedResultIterator<tsource, tkey, tresult> : IEnumerable<tresult>, IEnumerator<tresult>
    {
        private enum State
        {
            New,
            Open,
            SourceEOF,
            Disposed
        }
        private State currentState;
        private readonly IEnumerator<tsource> _source;
        private readonly Func<tsource, tkey> _keySelector;
        private readonly Func<tkey, ienumerable<tsource>, IEnumerable<tresult>> _resultSelector;
        private TResult[] groupResult;

        private int position;

        public GroupedResultIterator(IEnumerator<tsource> source, Func<tsource, tkey> keySelector, Func<tkey, ienumerable<tsource>, IEnumerable<tresult>> resultSelector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));

            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));

            currentState = State.New;

            position = 0;

            _source = source;
            _keySelector = keySelector;
            _resultSelector = resultSelector;
        }
        
        public TResult Current
        {
            get
            {
                return groupResult[position];
            }
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }
        public IEnumerator<tresult> GetEnumerator()
        {
            return this;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this;
        }

        public void Dispose()
        {          
            groupResult = null;
            currentState = State.Disposed;
        }

        public bool MoveNext()
        {
            if (currentState == State.Disposed)
                return false;

            if (currentState == State.New)
            {
                currentState = State.Open;
                if (!_source.MoveNext())
                    currentState = State.SourceEOF;
            }

            if (groupResult == null || (position == groupResult.Length - 1 && currentState != State.SourceEOF))
            {
                var keyResult = new TResult[0];

                while (keyResult.Length == 0 && currentState != State.SourceEOF)
                    keyResult = GetResultForKey(_keySelector(_source.Current));

                groupResult = keyResult;
                position = -1;
            }

            if (currentState == State.SourceEOF && groupResult.Length == 0 || position == groupResult.Length - 1)
                return false;

            position++;
            return true;
        }

        public void Reset()
        {
            throw new NotImplementedException();
        }

        private TResult[] GetResultForKey(TKey key)
        {
            var buffer = new List<tsource>();

            if (key == null)
            {
                buffer.Add(_source.Current);
                if (!_source.MoveNext())
                {
                    currentState = State.SourceEOF;
                }
            }
            else
                while (key.Equals(_keySelector(_source.Current)))
                {
                    buffer.Add(_source.Current);
                    if (!_source.MoveNext())
                    {
                        currentState = State.SourceEOF;
                        break;
                    }
                }
            return _resultSelector(key, buffer).ToArray();
        }
    }
</tsource></tresult></tresult></tkey,></tsource,></tsource></tresult></tkey,></tsource,></tsource></tresult></tresult></tsource,></tsource,></tresult></tkey,></tsource,></tsource></tsource,></tresult></code>
</pre>
<p>I have a hunch that this can just as well be solved with TPL Dataflow or Rx, but for now it seems sufficient.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Notes on the new DocumentDB partitioning and pricing]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The new pricing scheme and partitioning functionality for DocumentDB, made available at Build, was a significant improvement to the DocumentDB offering.</p>
<p>I learned about this a few weeks beforehand, but I did not fully see the benefits until I started looking at how this would effect our current solution.</p>
<h3 id="recap">Recap</h3>]]></description><link>https://ulriksenblog.azurewebsites.net/notes-on-documentdb-partitioning/</link><guid isPermaLink="false">5e2472562807240001af2c92</guid><category><![CDATA[Azure]]></category><category><![CDATA[DocumentDB]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Tue, 24 May 2016 18:09:54 GMT</pubDate><media:content url="https://ulriksenblog.azurewebsites.net/content/images/2020/02/gabriel-sollmann-Y7d265_7i08-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/02/gabriel-sollmann-Y7d265_7i08-unsplash.jpg" alt="Notes on the new DocumentDB partitioning and pricing"><p>The new pricing scheme and partitioning functionality for DocumentDB, made available at Build, was a significant improvement to the DocumentDB offering.</p>
<p>I learned about this a few weeks beforehand, but I did not fully see the benefits until I started looking at how this would effect our current solution.</p>
<h3 id="recap">Recap</h3>
<p>With the old pricing model, one could choose between three performance levels per collection, from 250 to 2500 Request units.  Each collection could store a maximum of 10GB of data. This constraint is part of what drives the scalability of DocumentDB. One was forced to prepare the data for sharding. Combined with the predictable request charge of queries it was possible to calculate the required collection count, size and cost. However, should the need for re-sharding occur, it would be a manual task and it would also require a strategy for handling reads and writes during the re-partitioning of the data. Not to mention that this operation would require RUs as well, often on a system under stress.</p>
<p>With this pricing scheme my recommendation was to aim for S1 collections at 1K RU for normal operations, scaling down to S0 during night/low traffic periods and leaving the S2 for high traffic usage or re-sharding.</p>
<h3 id="enterpartitionedcollections">Enter Partitioned collections</h3>
<p>So, instead of letting you deal with this, the DocumentDB created Partitioned collections. In reality it's just a bunch of collections and instead of paying per collection you just pay for the size used and request units needed. You no longer need to think about re-sharding and leaving RU's available for this operation.</p>
<blockquote>
<p>Partitioned collections removes a lof of Yak hair for Operations</p>
</blockquote>
<p>So, what do you need to think of with Partitioned Collections? Well, each partition still has some limits, it's still 10GB and 10K RU and the partition also acts as the transactional and query boundary. What does this mean?</p>
<ul>
<li>You want enough partition keys with a meaningfull distribution</li>
<li>Make sure your data is evenly distributed over your keys.</li>
<li>Make sure to query with partition key</li>
</ul>
<p>With just a few keys you will not write to all collections. With a bad spread of the keys, you can risk having a hot partition. Also, if a significant amount of your data is related to one partition key you will have a problem</p>
<p>The Request Charge for a query will drastically increase if you do multi-partition querys as the query is parsed and executed per. collection. One can experience as much as a 25x increase in RU cost for unbounded queries.</p>
<p>But, in overall this change in pricing and functionality is great! These are problems you would have had with the old as well. It's just that you would have to deal with a lot more yak shaving as well.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Indexing changes in DocumentDB]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>TL;DR;<br>Hash indexing is dead, long live Range indexing</p>
</blockquote>
<p>I recently did a <a href="https://azure.microsoft.com/nb-no/services/documentdb/">DocumentBD</a> talk for NNUG in Oslo, and made a discovery during my preparation of a demo on <a href="https://azure.microsoft.com/nb-no/documentation/articles/documentdb-indexing-policies/">indexing</a>.</p>
<p>The default index configuration when creating a collection in the portal differs from creating one with the API</p>]]></description><link>https://ulriksenblog.azurewebsites.net/indexing-changes-in-documentdb/</link><guid isPermaLink="false">5e2472562807240001af2c91</guid><category><![CDATA[DocumentDB]]></category><category><![CDATA[Azure]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Fri, 29 Apr 2016 07:10:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>TL;DR;<br>Hash indexing is dead, long live Range indexing</p>
</blockquote>
<p>I recently did a <a href="https://azure.microsoft.com/nb-no/services/documentdb/">DocumentBD</a> talk for NNUG in Oslo, and made a discovery during my preparation of a demo on <a href="https://azure.microsoft.com/nb-no/documentation/articles/documentdb-indexing-policies/">indexing</a>.</p>
<p>The default index configuration when creating a collection in the portal differs from creating one with the API and also the documentation. Both the API and Documentation follows the &quot;old&quot; indexing settings[1] but this will show up as Custom in the portal.</p>
<p>Creating a collection using the portal, the new default is range for both string and numbers. It will also display as default settings in the portal.</p>
<p><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/defaultindexing.png" alt="defaultindexing"><br>
Another observation is the new default indexing for the point datatype, points will now by default be indexed for <a href="https://azure.microsoft.com/nb-no/documentation/articles/documentdb-geospatial/">spatial</a> searchs.</p>
<p>I've reached out to the DocumentDB team, and apperantly they are changing the indexing a bit. As far as I understand they have optimized the storage for range, so that the difference between hash and range are very small. This may lead to the deprecation of hash indexing. This is a good thing, a simple product means less developer surprises and frustration.</p>
<p>In my dream world, this is a step on the road to skip and take functionality. The DocumentDB closely monitors our wishlist, so please take your time to upvote skip/take <a href="https://feedback.azure.com/forums/263030-documentdb/suggestions/6350987--documentdb-allow-paging-skip-take">here</a>.</p>
<p>[1] Code for old/API indexing settings,</p>
<pre><code>{
  &quot;indexingMode&quot;: &quot;consistent&quot;,
  &quot;automatic&quot;: true,
  &quot;includedPaths&quot;: [
    {
      &quot;path&quot;: &quot;/*&quot;,
      &quot;indexes&quot;: [
        {
          &quot;kind&quot;: &quot;Range&quot;,
          &quot;dataType&quot;: &quot;Number&quot;,
          &quot;precision&quot;: -1
        },
        {
          &quot;kind&quot;: &quot;Hash&quot;,
          &quot;dataType&quot;: &quot;String&quot;,
          &quot;precision&quot;: 3
        }
      ]
    }
  ],
  &quot;excludedPaths&quot;: []
}
</code></pre>
<p>[2]New indexing settings</p>
<pre><code>{
  &quot;indexingMode&quot;: &quot;consistent&quot;,
  &quot;automatic&quot;: true,
  &quot;includedPaths&quot;: [
    {
      &quot;path&quot;: &quot;/*&quot;,
      &quot;indexes&quot;: [
        {
          &quot;kind&quot;: &quot;Range&quot;,
          &quot;dataType&quot;: &quot;Number&quot;,
          &quot;precision&quot;: -1
        },
        {
          &quot;kind&quot;: &quot;Range&quot;,
          &quot;dataType&quot;: &quot;String&quot;,
          &quot;precision&quot;: -1
        },
        {
          &quot;kind&quot;: &quot;Spatial&quot;,
          &quot;dataType&quot;: &quot;Point&quot;
        }
      ]
    }
  ],
  &quot;excludedPaths&quot;: []
}
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Benefits of having an open source project]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>During Desember last year I created an open source project called DoubleCache. It's a cleaner version of a cache pattern we use at work, written from scratch.</p>
<h3 id="tldr">TL;DR</h3>
<ul>
<li>Great source for a conference talk</li>
<li>Helped me learn FAKE and Appveyor</li>
<li>Made me reason about handling pull requests, figuring out</li></ul>]]></description><link>https://ulriksenblog.azurewebsites.net/benefits-of-having-an-open-source-project/</link><guid isPermaLink="false">5e2472562807240001af2c90</guid><category><![CDATA[DoubleCache]]></category><category><![CDATA[OpenSource]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Fri, 01 Apr 2016 17:18:16 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>During Desember last year I created an open source project called DoubleCache. It's a cleaner version of a cache pattern we use at work, written from scratch.</p>
<h3 id="tldr">TL;DR</h3>
<ul>
<li>Great source for a conference talk</li>
<li>Helped me learn FAKE and Appveyor</li>
<li>Made me reason about handling pull requests, figuring out a how I prefer to do this (blogpost coming).</li>
<li>Showcase skills and thoughts for potential customers and employers.</li>
</ul>
<h3 id="indetails">In details</h3>
<p>The first benefit my open source project gave me was backing up a talk I had planned for the Norwegian .Net user group. The talk was about Redis and our experiences of moving to a centralized cache. Backing the talk with my own implementation provided very clear samples.</p>
<p>Truth be told, DoubleCache wasn't yet public when I did my talk, but it became public a couple of days later. Pushing code out in the open forced me to setup a proper build and test setup, something I might not have done had it been a private project. With an actual need to learn <a href="http://fsharp.github.io/FAKE/">FAKE</a> it was easy to get the Instant Gratification Monkey out of the way<a href="http://waitbutwhy.com/2013/10/why-procrastinators-procrastinate.html">[1]</a>. I prefer <a href="https://xunit.github.io/">xUnit</a> and <a href="https://github.com/shouldly/shouldly">shoudly</a> when writing C#, and this meant I had to dig into FAKE to a degree where I now feel comfortable with it.</p>
<p>It did not take long time before I had the first pull request, this one from a colleague but never the less I learned how to use <a href="https://www.appveyor.com/">AppVeyor</a>. Well, not much to learn really when using FAKE. Having all your build configurations under version control is just great.</p>
<p>After yet another talk, I got the first pull request from someone I did not know, <a href="https://github.com/cbigsby">Clayton Sayer</a>. He's done some great things, fixed a few configuration issues, added delete functionality and synchronous support. After looking at our repository at work and reading a few blogposts, I was sure that I wanted single commits when merging pull requests. I needed a way to do this, and at the same time be able to make modifications such as bumping the version number in the build script. More on this in the next blog post.</p>
<p>Finally, putting code out in the open forced me to think things through more than once. Not just because it's public, but it will serve as part of my resume. It will without doubt be a discussion point when talking to potential customers or future employers.</p>
<p>It has been, and continue to be, a great experience.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Unit testing Redis Lua scripts]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>With great power comes great responsibility. The power of Lua scripting with Redis and what you can achieve using data structures beyond a key/value store is amazing. Starting out is quick and easy, and with some VIM tricks you can easily create an efficient feedback loop.</p>
<blockquote>
<p>But then what,</p></blockquote>]]></description><link>https://ulriksenblog.azurewebsites.net/unit-testing-redis-lua-scripts/</link><guid isPermaLink="false">5e2472562807240001af2c8f</guid><category><![CDATA[Azure]]></category><category><![CDATA[Redis]]></category><category><![CDATA[scalability]]></category><category><![CDATA[Cache]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 17 Mar 2016 18:32:44 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>With great power comes great responsibility. The power of Lua scripting with Redis and what you can achieve using data structures beyond a key/value store is amazing. Starting out is quick and easy, and with some VIM tricks you can easily create an efficient feedback loop.</p>
<blockquote>
<p>But then what, after a few iterations, how do you know that your scripts are still working?</p>
</blockquote>
<p>Well, there's no reason not to include your Lua scripts in a test regime. To do this we can &quot;simply&quot; fire up a Redis server as a part of our tests. Now, you could argue that these are integration tests as we're using a service running out of process and perhaps that's right. But these tests run so fast, and are so specific, that I prefer to run them as a part of my development cycle. They're also executed alongside our regular unit tests, not our integration tests.</p>
<h3 id="tldr">TL;DR</h3>
<p>How does it work? We reference a redis server, start the server, execute our tests, and shutdown.</p>
<h3 id="stepbystepcreatingourtestproject">Step by step - creating our test project</h3>
<ol start="0"> 
<li>Here's our system under test, a small and rather useless script for adding a key value to the cache. 
```
  public class SomeServiceUsingLuaScript
  {
    private IConnectionMultiplexer _redisConnection;
    public SomeCacheService(IConnectionMultiplexer redisConnection)
    {
      _redisConnection = redisConnection;
    }
    public void RunsALuaScript(string value)
    {
        _redisConnection.GetDatabase().ScriptEvaluate(string.Format("redis.call('set','test','{0}')", value));
    }
  }
```
</li>
<li>Create a new class library for your tests
</li>
<br>
<li>Use nuget and add references to Redis-64, StackExchange.Redis, xunit.core, xunit.runner.visualstudio and Shouldly
```
Install-Package Redis-64
Install-Package StackExchange.Redis
Install-Package xunit.core
Install-Package xunit.runner.visualstudio
Install-Package Shouldly
```
</li>
<li>Create a folder called Redis4. As linked files, add  redis-server.exe and redis.windows.conf from .\packages\redis-64.3.0.501\tools\ and set the Copy to output property to "Copy if newer"</li>
<br>
<li> To make sure we start the server once for all our tests we'll use the class and collection Fixture from xunit. The class fixture will be responsible for starting the redis server, and the collection fixture will allow us to run multiple test classes with the same instance of the class fixture. For small and closely related classes I prefer to keep them in the same file. Create a new file called RedisFixture.cs with the following content
```
[CollectionDefinition("RedisCollection")]
public class RedisCollectionFixture : ICollectionFixture<redisfixture>
{
  //// Marker class for Collection Fixture
}
<p>public class RedisFixture : IDisposable<br>
{<br>
private static Process redisProcess;</p>
<p>public RedisFixture()<br>
{<br>
if (redisProcess == null || redisProcess.HasExited)<br>
redisProcess = StartRedis();<br>
}</p>
<p>public void Dispose()<br>
{<br>
try<br>
{<br>
if (redisProcess != null)<br>
{<br>
if (redisProcess.HasExited)<br>
return;</p>
<pre><code>    redisProcess.StandardInput.WriteLine(&quot;SHUTDOWN&quot;);
    Thread.Sleep(500);

    if (!redisProcess.HasExited)
      redisProcess.Kill();
    redisProcess.Dispose();
  }
}
catch
{

}
</code></pre>
<p>}</p>
<pre><code>&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;We can now write our first test using Redis
</code></pre>
<p>[Collection(&quot;RedisCollection&quot;)]<br>
public class MyLuaScriptTests<br>
{<br>
[Fact]<br>
public void RunALuaScriptTest()<br>
{<br>
var connection = ConnectionMultiplexer.Connect(&quot;localhost&quot;);<br>
var service = new SomeCacheService(connection);</p>
<pre><code>  service.RunsALuaScript(&quot;a&quot;);

  var result = (string)connection.GetDatabase().StringGet(&quot;test&quot;);
  result.ShouldBe(&quot;a&quot;);
}
</code></pre>
<p>}</p>
<pre><code>&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;The test is now available in the Visual studio test explorer (it may fail running if you're using the 2.1.0 version of the xunit.runner.visualstudio. In that case, try to downgrade it to 2.0.1).  During the first test exection you may be prompted to adjust firewall settings, as Redis binds to a tcp port. 
&lt;/ol&gt;
You're now ready to write Lua scripts for Redis in a safe and sound manner. </code></pre>
<!--kg-card-end: markdown--></redisfixture></li></ol>]]></content:encoded></item><item><title><![CDATA[Turn up the beat, heart rate of a speaker]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Beginning of January I was contacted by the Bitshift meetup organizers, asking if I could come over and do a talk or two. Having two talks more or less prepared I decided that it could be a fun experience and also great practice. I gave a talk on caching (<a href="http://www.slideshare.net/HaraldSchultUlriksen/cache-bonanza">slides</a></p>]]></description><link>https://ulriksenblog.azurewebsites.net/heart-rate-of-a-speaker/</link><guid isPermaLink="false">5e2472562807240001af2c8c</guid><category><![CDATA[public speaking]]></category><category><![CDATA[bitshift]]></category><category><![CDATA[nnug]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Wed, 10 Feb 2016 19:33:52 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Beginning of January I was contacted by the Bitshift meetup organizers, asking if I could come over and do a talk or two. Having two talks more or less prepared I decided that it could be a fun experience and also great practice. I gave a talk on caching (<a href="http://www.slideshare.net/HaraldSchultUlriksen/cache-bonanza">slides</a>),  and one on the architecture behind personalization of <a href="http://tv.nrk.no">http://tv.nrk.no</a>, (<a href="http://www.slideshare.net/HaraldSchultUlriksen/personalisering-av-tvnrkno">slides</a>).</p>
<p>Before and during my previous talks I have noticed my heart rate goes somewhat haywire, so I decided it could be fun to track it during a talk. As I got on stage setting up and having a chat with one of the organizers I turned on my garmin and noticed straight away that I was having a small workout, that's a 140bpm. Apparently something happened about 5 minutes in, my pulse peaked out at 165 bmp. Here's the whole story<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/heartrate.png" alt="heartrate"><br>
We had a break about an hour in before we started again, easy to spot.</p>
<p>I have a tendency to talk a bit fast, and also run demos waaay too fast. Heart rate may be a part of it, and I will keep tracking it to see if I can managed to calm down a bit. The first chance seems to be April 26th, when I will give a talk on DocumentDb for NNUG Oslo</p>
<p>Bitshift was a great experience, and it was really fun talking about something I care about and engage me. I was also surprised by the strong turnout, about the same as we see in Oslo.</p>
<p>Thanks for having me.<br>
<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/bitshift-1.jpg" alt="bitshift-1"><br>
Picture by <a href="http://twitter.com/olavamjelde">http://twitter.com/olavamjelde</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Isolating failures - deliver what you can]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>If some of your functionality fails, should it take your website down?</p>
</blockquote>
<p>Let's say you have a frontpage of a webshop displaying promoted items, a campaign and a list of the most popular items. If you fail fetching the popular items, or have some invalid data in it which throws</p>]]></description><link>https://ulriksenblog.azurewebsites.net/isolating-failure-deliver-what-you-can/</link><guid isPermaLink="false">5e2472562807240001af2c8b</guid><category><![CDATA[BlackFriday]]></category><category><![CDATA[scalability]]></category><category><![CDATA[performance]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Tue, 12 Jan 2016 19:48:40 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>If some of your functionality fails, should it take your website down?</p>
</blockquote>
<p>Let's say you have a frontpage of a webshop displaying promoted items, a campaign and a list of the most popular items. If you fail fetching the popular items, or have some invalid data in it which throws an exception, having the whole frontpage fail would be really bad. You want the rest of the page to render.</p>
<p>This happened to us recently, a part of the frontpage failed. But instead of killing the  whole page, only the failing feature failed. Here's how it looks when you enter the page<br>
<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/frontpage1.jpg" alt="frontpage1"><br>
and below you have the failing functionality - in this case it was not even visible to the user until they clicked the &quot;sist sent&quot; (recently aired) tab. Crashing our whole page because of this would be plain out stupid.<br>
<img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/frontpage2.jpg" alt="frontpage2"><br>
This is just as much about isolating features as isolating failures. By isolating features we can start applying several patterns which will help in creating a responsive and well behaved page:</p>
<ol>
<li>
<p>Circuit breaker for each feature/system. If the system is down, deliver what you got.</p>
</li>
<li>
<p>Timeouts per feature - if the most popular items feature will exceed your response time requirements, treat it as a fail and deliver what you got. That's better than building the request queue with waiting clients.</p>
</li>
<li>
<p>Cache - we can cache each part by itself. If we know when feature A and B changes but not C - we can pre-compute A and B and update the cache, or at least invalidate it. C can then have a less agressive cache setting.</p>
</li>
</ol>
<p>So, by isolating your features you should be able to deliver some value to the user even if a part of your system is in error.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Introducing DoubleCache]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>DoubleCache, <a href="https://github.com/AurumAS/DoubleCache">https://github.com/AurumAS/DoubleCache</a>, is my own open source implementation of a layered distributed cache, it builds upon solid projects like <a href="http://redis.io/">Redis</a>, <a href="https://github.com/StackExchange/StackExchange.Redis">StackExchange.Redis</a> and <a href="https://github.com/msgpack/msgpack-cli">MsgPack</a> and combines these with a local cache implementation on the .Net stack.</p>
<h2 id="somehistory">Some history</h2>
<p>We're already running a similar solution with my</p>]]></description><link>https://ulriksenblog.azurewebsites.net/introducing-doublecache/</link><guid isPermaLink="false">5e2472562807240001af2c8a</guid><category><![CDATA[Azure]]></category><category><![CDATA[Redis]]></category><category><![CDATA[DoubleCache]]></category><category><![CDATA[Cache]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Wed, 06 Jan 2016 06:15:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>DoubleCache, <a href="https://github.com/AurumAS/DoubleCache">https://github.com/AurumAS/DoubleCache</a>, is my own open source implementation of a layered distributed cache, it builds upon solid projects like <a href="http://redis.io/">Redis</a>, <a href="https://github.com/StackExchange/StackExchange.Redis">StackExchange.Redis</a> and <a href="https://github.com/msgpack/msgpack-cli">MsgPack</a> and combines these with a local cache implementation on the .Net stack.</p>
<h2 id="somehistory">Some history</h2>
<p>We're already running a similar solution with my current customer, <a href="https://tv.nrk.no/">NRK</a>. Our motivation for creating this, came after migrating from <a href="https://azure.microsoft.com/nb-no/blog/azure-managed-cache-and-in-role-cache-services-to-be-retired-on-11-30-2016/">Azure Managed Cache</a> to <a href="https://azure.microsoft.com/nb-no/services/cache/">Azure Redis Cache</a>. Azure Managed cache has the nice feature of a local cache on the client, in front of the Managed cache. This is not available when using Redis, as Microsoft has not created their own client, instead they recommend using the (excellent) StackExchange.Redis client. When we moved to Redis, our CPU went haywire as we did a LOT of cache requests (often way too many, it's hard to notice when you hit local memory) and used BinaryFormatter for serialization. Besides cleaning up our data access, we needed our own layered cache. Our layered implementation over StackExchange.Redis is quite OK, however it is a bit tangled with old interfaces and not something which can be easily reused by others. DoubleCache aims to fix this.</p>
<h2 id="mygoalswhencreatingdoublecache">My goals when creating DoubleCache</h2>
<p>I created DoubleCache for a meetup where I talked about the penalties of moving to a remote cache, and I needed some code to highlight the <a href="http://blog.ulriksen.net/single-digit-response-times/">problems</a> with remote caches. As I wanted a clean implementation and other open source projects were too messy, I decided to implement my own with the following criteria</p>
<ol>
<li>It should be possible to use as a local, remote or local and remote cache - with or without sync, through a single interface. Changing from a local to a remote cache should not require any changes in the client using it besides swapping interface implementation.</li>
<li>Each implementation should in it self be trivial</li>
<li>Follow the cache aside pattern</li>
<li>Extending the functionality should not require any modifications to existing imeplementations. Using standard patterns such as decorator ought to do it.</li>
<li>Serialization must be pluggable.</li>
</ol>
<h2 id="usage">Usage</h2>
<p>Add a reference to DoubleCache using nuget <code>Install-Package DoubleCache</code> and initialize the DoubleCache with a remote and a local cache.</p>
<pre><code>var connection = ConnectionMultiplexer.Connect(&quot;localhost&quot;);
var serializer = new MsgPackItemSerializer();

_pubSubCache = CacheFactory.CreatePubSubDoubleCache(connection, serializer);
</code></pre>
<p>To use the cache call the GetAsync&lt;T&gt; method. This method takes a Func called dataRetriever. This method should call your repository or other service. The dataRetriever method executes if the requested key does not exist in the cache, adding the result to the cache.</p>
<pre><code>var cacheKey = Request.RequestUri.PathAndQuery;

pubSubCache.GetAsync(cacheKey, () =&gt; _repo.GetSingleDummyUser()));
</code></pre>
<h2 id="implementation">Implementation</h2>
<p>The ICacheAside interface is the main part of DoubleCache, all variants relies on implementations of this single interface.</p>
<pre><code>    public interface ICacheAside
    {
        void Add&lt;T&gt;(string key, T item);
        void Add&lt;T&gt;(string key, T item, TimeSpan? timeToLive);

        Task&lt;T&gt; GetAsync&lt;T&gt;(string key, Func&lt;Task&lt;T&gt;&gt; dataRetriever) where T : class;
        Task&lt;T&gt; GetAsync&lt;T&gt;(string key, Func&lt;Task&lt;T&gt;&gt; dataRetriever, TimeSpan? timeToLive) where T : class;

        Task&lt;object&gt; GetAsync(string key, Type type, Func&lt;Task&lt;object&gt;&gt; dataRetriever);
        Task&lt;object&gt; GetAsync(string key, Type type, Func&lt;Task&lt;object&gt;&gt; dataRetriever, TimeSpan? timeToLive);
    }
</code></pre>
<p>The Add method is implemented with fire and forget, hence it does not need to be Async as this is handled by the Stackexchange.Redis client.</p>
<p>DoubleCache comes with the following implementations of this interface</p>
<ul>
<li>LocalCache.MemCache - using System.Runtime.Memory</li>
<li>Redis.RedisCache - using StackExchange.Redis client</li>
<li>DoubleCache - a decorator wrapping a local and a remote cache</li>
<li>PublishingCache - a decorator publishing cache changes</li>
<li>SubscribingCache - a decorator supporting push notifications of cache updates</li>
</ul>
<p>As seen in the usage example, combining the decorators and implementations provide a high level of flexibility. It comes at a little mental cost when wiring up the DoubleCache constructor. This can be relieved to hide the constructor behind a factory method.</p>
<h4 id="localcachememcache">LocalCache.MemCache</h4>
<p>This uses the <code>System.Runtime.Caching.MemoryCache.Default</code> instance throughout the implementation.</p>
<blockquote>
<p>A word of warning: These are mutable objects stored in memory. Be careful if you modify items retrieved from the cache. There can be only one.</p>
</blockquote>
<h4 id="redisrediscache">Redis.RedisCache</h4>
<p>A wrapper around StackExchange.Redis. Since the IConnectionMultiplexer should be a single instance, you will need to pass the Redis database in the constructor. The StringSet call to Redis use the FireAndForget option.</p>
<h4 id="doublecache">DoubleCache</h4>
<p>This is a decorator used to wire the local and remote cache together.</p>
<p>To achieve this, it simply calles the local cache first and wraps the remote cache in the dataRetriever function.</p>
<pre><code>return _localCache.GetAsync(key, type, () =&gt; _remoteCache.GetAsync(key, type, dataRetriever), timeToLive);
</code></pre>
<p>While DoubleCache will keep the remote cache in sync with any add calls made on the local cache it owns, syncing the local cache with remote cache changes triggered by other clients is not the responsibility of the DoubleCache wrapper. This is covered by the publishing and subscribing cache wrappers.</p>
<h4 id="publishingcache">PublishingCache</h4>
<p>A decorator for publishing changes when adding/updating items in the cache. The key and object type is published using the ICachePublisher interface, which then passes the message on to Redis Pub/Sub. As each cache implementation is responsible for adding an item to itself when the dataRetriever function is executed, ICachePublisher wraps this method causing a cache publish after it is executed.</p>
<pre><code>public Task&lt;T&gt; GetAsync&lt;T&gt;(string key, Func&lt;Task&lt;T&gt;&gt; dataRetriever) where T : class
{
    return  _cache.GetAsync(key, async() =&gt; {
        var result = await dataRetriever.Invoke();
        _cachePublisher.NotifyUpdate(key, result.GetType().AssemblyQualifiedName);
        return result;
    });
}
</code></pre>
<p>The publishing cache is intended to wrap the remote/central cache implementation.</p>
<h4 id="subscribingcache">Subscribing cache</h4>
<p>This decorator wraps a cache and through the implementation of ICacheSubscriber it will call Add on the wrapped cache when the ICacheSubscriber.CacheUpdate event is fired. The RedisSubscriber implementation of ICacheSubscriber will also need a reference to the remote cache, as the Pub/Sub message does not contain the cache item itself, only the key and the type.</p>
<p>The Subscribing cache decorator is intended to wrap the local cache.</p>
<h3 id="serialization">Serialization</h3>
<p>As mentioned in in my post on cache speed, there are a lot of options when it comes to serializers. By default, DoubleCache comes with BinaryFormatter and MsgPack.</p>
<p>If your data-types support it, I highly recommend something other than BinaryFormatter.</p>
<p>To implement another serializer you will need to implement the IItemSerializer interface</p>
<pre><code>    public interface IItemSerializer
    {
        byte[] Serialize&lt;T&gt;(T item);

        T Deserialize&lt;T&gt;(byte[] bytes);
        T Deserialize&lt;T&gt;(Stream stream);
        object Deserialize(byte[] bytes, Type type);
    }
</code></pre>
<h2 id="whatsnext">Whats next</h2>
<p>I have a few open issues on GitHub which I intend to close:</p>
<ol>
<li>Passing TimeToLive with pub/sub, or retrieving it from the cache</li>
<li>Creating a factory to make it simpler to get started</li>
<li>Adding delete operations</li>
</ol>
<p>You'll find DoubleCache over at GitHub <a href="https://github.com/AurumAS/DoubleCache">https://github.com/AurumAS/DoubleCache</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Single digit response times]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Single digit response times are fully possible. And I think we should try to get there, it may not always be possible but that's no reason not to explore our options. A fast site will feel more responsive, and using less resources means that you can handle massive load on</p>]]></description><link>https://ulriksenblog.azurewebsites.net/single-digit-response-times/</link><guid isPermaLink="false">5e2472562807240001af2c89</guid><category><![CDATA[Cache]]></category><category><![CDATA[BlackFriday]]></category><category><![CDATA[scalability]]></category><category><![CDATA[redis]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Sun, 03 Jan 2016 20:04:40 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Single digit response times are fully possible. And I think we should try to get there, it may not always be possible but that's no reason not to explore our options. A fast site will feel more responsive, and using less resources means that you can handle massive load on less resources.</p>
<p>Caching content is perhaps the single most effective measure. Living in a web world we have three main ways to go</p>
<ol>
<li>Http caching (think <a href="https://tools.ietf.org/html/rfc7234">RFC7234</a> and headers such as max-age, etags and If-Modified-Since)</li>
<li>Output cache, either built-in or products like Varnish</li>
<li>Application cache.</li>
</ol>
<p>In this post we're going to look at the last of these, the one closest to your stack. This is where you end up when you need to alter the response before you emit data from the server.</p>
<p>Starting out with a small solution, often hosted on a single server, the application cache normally lives in-memory and the objects are kept as is. It's fast and relatively easy, the memory management is often taken care of for you.</p>
<p>After a while your application grows, you have multiple servers and having local caches may no longer be optimal. Problems such as cache sync arise - serving the same user different data just because the user ended up on a different server makes your application feel britle and awkward. Enter the remote cache. These days often implemented using <a href="http://redis.io/">Redis</a> (Redis is really on a roll with both AWS and Microsoft offering Redis as a service).</p>
<p>So, what happens when you switch from a local cache to a remote cache? You get two penalties</p>
<ol>
<li>Network IO</li>
<li>Serialization</li>
</ol>
<p>Redis is fast, we're talking about 6-8ms response times with network IO and serialization, but when your goal is single digit response times, that's too much.</p>
<p>So, how can we have both? A layered cache, using both a remote cache and a local cache. This also plays well with this cloud thing where instances pop up when needed and instance memory is not really expensive.</p>
<blockquote>
<p>How much memory do you really need to keep your entire site in memory?</p>
</blockquote>
<p>To get this to play well we also need to</p>
<ol>
<li>Keep our local caches in sync</li>
<li>A fast serialization when we hit the remote cache</li>
</ol>
<p>To keep our local caches in sync we need a pub/sub mechanism, Redis has this built in and makes the implementation quite trivial. It's not a reliable sync, i.e. the messages are published, if a client is disconnected for some reason, it will not get the updated. I find that this is something we normally can live with.</p>
<p>The serialization part of it is also solved for us, there are several fast serialization procotols available to us, such as <a href="http://msgpack.org/">MsgPack</a>, <a href="https://github.com/mgravell/protobuf-net">Protobuf</a>, <a href="https://github.com/Microsoft/bond">Bond</a> or <a href="http://avro.apache.org/">Avro</a>. You will find that these protocols have their pros and cons, In .Net land MsgPack does not require class markup, but cannot cope with inheritance. Protobuf can, but requires a serialization definition. Yan Cui has a nice benchmark over at <a href="http://theburningmonk.com/benchmarks/">http://theburningmonk.com/benchmarks/</a>.</p>
<blockquote>
<p>What ever you do, BinaryFormatter is slow.</p>
</blockquote>
<p>So, by creating a layered distributed cache we can achieve fast response times and a synchronized cache. As an added benefit we can use the pub/sub mechanism to push data changes to the cache from other services. This comes in real handy in the microservices world.</p>
<p><a href="https://github.com/AurumAS/DoubleCache">DoubleCache</a> is my own implementation of a layered distributed cache for .Net. Using Redis as the remote storage, and System.Runtime.MemoryCache (can easily be switched to HttpCache). I've tried to stick to a single interface, making it possible to switch between a local cache, remote cache, local and remote, or a synced local and remote cache. The implementation follows the cache-aside and decorator patterns.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Availability in an unreliable cloud]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>One of the first problems to solve when moving to the cloud is availability, or just plain uptime. Although it seems strange that the cloud should not be stable, but this is one of the constraints that is an enabler for solid solutions. By accepting unexpected service interuptions as a</p>]]></description><link>https://ulriksenblog.azurewebsites.net/availability-in-an-unreliable-cloud/</link><guid isPermaLink="false">5e2472562807240001af2c88</guid><category><![CDATA[Azure]]></category><category><![CDATA[cloud]]></category><dc:creator><![CDATA[Harald Schult Ulriksen]]></dc:creator><pubDate>Thu, 10 Dec 2015 19:08:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>One of the first problems to solve when moving to the cloud is availability, or just plain uptime. Although it seems strange that the cloud should not be stable, but this is one of the constraints that is an enabler for solid solutions. By accepting unexpected service interuptions as a design requirement, the whole solution benefits. You have to design for failure and outages. Think Netflix and their <a href="http://techblog.netflix.com/search/label/simian%20army">simian army</a>.</p>
<p><img src="https://ulriksenblog.azurewebsites.net/content/images/2020/01/simian.png" alt="simian"></p>
<p>Outages in the cloud can be placed in two categories, failures or maintenance, and within maintenance we have planned and unplanned maintenance. To deal with this, and also to meet the SLA requirements, Microsoft has divided Azure into update domains and fault domains. Update domains are related to restarts due to maintenance and upgrades, while fault domains are closely related to HW, such as a rack or power unit <a href="https://azure.microsoft.com/nb-no/documentation/articles/virtual-machines-manage-availability/">https://azure.microsoft.com/nb-no/documentation/articles/virtual-machines-manage-availability/</a>. It is therefore important to have multiple instances, at least one in each fault domain, preferably also one in each update domain. Once you have enough instances you will survive downtime.</p>
<p>Next step on the availability list is to support datacenter outages. To deal with this, one can start using multiple datacenters, potentially from different cloud providers, i.e. use one Azure DS and one Amazon DS. Your ability to move between cloud vendors will normally be limited by the choice of technology and implementation. Architecting for multi-vendor support will require a lot more work when it comes to operations and management. Any SAAS platform must have an equivalent offering with both vendors, not to mention how you will work with the different performance characteristics.</p>
<h3 id="serviceoverview">Service overview</h3>
<p>Here's a short list of some of the Azure services and how replication works.</p>
<table>
<thead>
<tr>
<th style="width: 150px">Service</th><th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: top">Azure storage</td>
<td>Azure storage comes in four different flavors:
<div style="width: 500px"><img src="https://ulriksenblog.azurewebsites.net/content/images/2015/12/storageReplication.png"></div>
From https://azure.microsoft.com/nb-no/documentation/articles/storage-redundancy/. Note that Zone Redundant storage is only available for block blobs. 
</td>
</tr>
<tr>
<td style="vertical-align: top">
Azure SQL 
</td>
By default SQL is replicated to 3 severs in each datacenter, on the premium level a SQL database can be set to active replication. Also, the secondary SQL servers can be used as a read source, however this may hold locks and cause transactions to fail on the master. https://azure.microsoft.com/en-us/documentation/articles/sql-database-geo-replication-overview/#active-geo-replication-capabilities

</tr>
<tr>
<td style="vertical-align: top">DocumentDb
</td>
<td>Each collection in DcumentDb resides on multiple servers, however there's no built in geo-replication.</td>
</tr>
<tr>
<td style="vertical-align: top">Redis</td>
<td>The basic Redis offering is not replicated. At the standard level there's a master and a slave. And in the recently announced Premium tier there's support for Redis clustering, sharding data over multiple nodes. https://azure.microsoft.com/en-us/documentation/articles/cache-how-to-premium-clustering/</td>
</tr>
<tr>
<td style="vertical-align: top">Search
</td>
<td>Search is divided in replicas and partitions. For read-write and indexing availability, at least 3 replicas are needed. Partitions relates to the storage volume.</td>
</tr>
<tr>
<td>Cloud services</td>
<td>The number of instances determines how good you can handle outages. You need at least one in each fault domain, preferably at least instances. 
</td></tr>
<tr>
<td>Cloud services/Virtual machines</td>
<td>The number of instances determines how good you can handle outages. You need at least two or more in an availability set/one in each fault domain.. 
</td></tr>
</tbody>
</table>
As we see, all of these services provide some sort of replication. Some offer geo redundancy, but in many cases you will not be able to control this in details yourself. From a performance perspective, this landscape changes with each server, as an example can storage be manually sharded while this is an integral part of DocumentDb. 
<p>Also, while a few of these services provide geo replication, supporting writes is a completely different story. Especially if we go down the SAAS path, handling writes during outages are not trivial. It may often seem easier to use a PAAS and then run software designed for multiple datacenter usage on top of that instead. I've started writing on a post where we'll go through a sample setup on how we can achieve a solution built with Azure SAAS and still survive a datacenter outage.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>